OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/component_updater/component_patcher_operation_out_of_pr
ocess.h" | 5 #include "chrome/browser/component_updater/component_patcher_operation_out_of_pr
ocess.h" |
6 | 6 |
7 #include <memory> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | 7 #include "base/bind.h" |
11 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/files/file.h" |
12 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
13 #include "base/location.h" | 11 #include "base/sequenced_task_runner.h" |
14 #include "base/single_thread_task_runner.h" | 12 #include "base/strings/string16.h" |
15 #include "base/threading/thread_task_runner_handle.h" | |
16 #include "chrome/common/chrome_utility_messages.h" | |
17 #include "chrome/grit/generated_resources.h" | 13 #include "chrome/grit/generated_resources.h" |
18 #include "components/component_updater/component_updater_service.h" | |
19 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/utility_process_host.h" | |
21 #include "content/public/browser/utility_process_host_client.h" | |
22 #include "courgette/courgette.h" | |
23 #include "courgette/third_party/bsdiff/bsdiff.h" | |
24 #include "ipc/ipc_message_macros.h" | |
25 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
26 | 16 |
27 namespace component_updater { | 17 namespace component_updater { |
28 | 18 |
29 class PatchHost : public content::UtilityProcessHostClient { | 19 ChromeOutOfProcessPatcher::ChromeOutOfProcessPatcher() = default; |
30 public: | |
31 PatchHost(base::Callback<void(int result)> callback, | |
32 scoped_refptr<base::SequencedTaskRunner> task_runner); | |
33 | 20 |
34 void StartProcess(std::unique_ptr<IPC::Message> message); | 21 ChromeOutOfProcessPatcher::~ChromeOutOfProcessPatcher() = default; |
35 | |
36 private: | |
37 ~PatchHost() override; | |
38 | |
39 void OnPatchFinished(int result); | |
40 | |
41 // Overrides of content::UtilityProcessHostClient. | |
42 bool OnMessageReceived(const IPC::Message& message) override; | |
43 | |
44 void OnProcessCrashed(int exit_code) override; | |
45 | |
46 base::Callback<void(int result)> callback_; | |
47 scoped_refptr<base::SequencedTaskRunner> task_runner_; | |
48 }; | |
49 | |
50 PatchHost::PatchHost(base::Callback<void(int result)> callback, | |
51 scoped_refptr<base::SequencedTaskRunner> task_runner) | |
52 : callback_(callback), task_runner_(task_runner) { | |
53 } | |
54 | |
55 PatchHost::~PatchHost() { | |
56 } | |
57 | |
58 void PatchHost::StartProcess(std::unique_ptr<IPC::Message> message) { | |
59 // The DeltaUpdateOpPatchHost is not responsible for deleting the | |
60 // UtilityProcessHost object. | |
61 content::UtilityProcessHost* host = content::UtilityProcessHost::Create( | |
62 this, base::ThreadTaskRunnerHandle::Get().get()); | |
63 host->SetName(l10n_util::GetStringUTF16( | |
64 IDS_UTILITY_PROCESS_COMPONENT_PATCHER_NAME)); | |
65 host->Send(message.release()); | |
66 } | |
67 | |
68 bool PatchHost::OnMessageReceived(const IPC::Message& message) { | |
69 bool handled = true; | |
70 IPC_BEGIN_MESSAGE_MAP(PatchHost, message) | |
71 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Finished, OnPatchFinished) | |
72 IPC_MESSAGE_UNHANDLED(handled = false) | |
73 IPC_END_MESSAGE_MAP() | |
74 return handled; | |
75 } | |
76 | |
77 void PatchHost::OnPatchFinished(int result) { | |
78 if (task_runner_.get()) { | |
79 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result)); | |
80 task_runner_ = NULL; | |
81 } | |
82 } | |
83 | |
84 void PatchHost::OnProcessCrashed(int exit_code) { | |
85 if (task_runner_.get()) { | |
86 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, -1)); | |
87 task_runner_ = NULL; | |
88 } | |
89 } | |
90 | |
91 ChromeOutOfProcessPatcher::ChromeOutOfProcessPatcher() { | |
92 } | |
93 | |
94 ChromeOutOfProcessPatcher::~ChromeOutOfProcessPatcher() { | |
95 } | |
96 | 22 |
97 void ChromeOutOfProcessPatcher::Patch( | 23 void ChromeOutOfProcessPatcher::Patch( |
98 const std::string& operation, | 24 const std::string& operation, |
99 scoped_refptr<base::SequencedTaskRunner> task_runner, | 25 scoped_refptr<base::SequencedTaskRunner> task_runner, |
100 const base::FilePath& input_abs_path, | 26 const base::FilePath& input_path, |
101 const base::FilePath& patch_abs_path, | 27 const base::FilePath& patch_path, |
102 const base::FilePath& output_abs_path, | 28 const base::FilePath& output_path, |
103 base::Callback<void(int result)> callback) { | 29 base::Callback<void(int result)> callback) { |
104 host_ = new PatchHost(callback, task_runner); | 30 DCHECK(task_runner); |
105 IPC::PlatformFileForTransit input = IPC::TakePlatformFileForTransit( | 31 DCHECK(!callback.is_null()); |
106 base::File( | 32 |
107 input_abs_path, base::File::FLAG_OPEN | base::File::FLAG_READ)); | 33 task_runner_ = std::move(task_runner); |
108 IPC::PlatformFileForTransit patch = IPC::TakePlatformFileForTransit( | 34 callback_ = callback; |
109 base::File( | 35 |
110 patch_abs_path, base::File::FLAG_OPEN | base::File::FLAG_READ)); | 36 base::File input_file(input_path, |
111 IPC::PlatformFileForTransit output = IPC::TakePlatformFileForTransit( | 37 base::File::FLAG_OPEN | base::File::FLAG_READ); |
112 base::File( | 38 base::File patch_file(patch_path, |
113 output_abs_path, | 39 base::File::FLAG_OPEN | base::File::FLAG_READ); |
114 base::File::FLAG_CREATE | | 40 base::File output_file(output_path, base::File::FLAG_CREATE | |
115 base::File::FLAG_WRITE | | 41 base::File::FLAG_WRITE | |
116 base::File::FLAG_EXCLUSIVE_WRITE)); | 42 base::File::FLAG_EXCLUSIVE_WRITE); |
117 std::unique_ptr<IPC::Message> patch_message; | 43 |
| 44 if (!input_file.IsValid() || !patch_file.IsValid() || |
| 45 !output_file.IsValid()) { |
| 46 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, -1)); |
| 47 return; |
| 48 } |
| 49 |
| 50 content::BrowserThread::PostTask( |
| 51 content::BrowserThread::IO, FROM_HERE, |
| 52 base::Bind(&ChromeOutOfProcessPatcher::PatchOnIOThread, this, operation, |
| 53 base::Passed(&input_file), base::Passed(&patch_file), |
| 54 base::Passed(&output_file))); |
| 55 } |
| 56 |
| 57 void ChromeOutOfProcessPatcher::PatchOnIOThread(const std::string& operation, |
| 58 base::File input_file, |
| 59 base::File patch_file, |
| 60 base::File output_file) { |
| 61 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 62 DCHECK(!utility_process_mojo_client_); |
| 63 |
| 64 const base::string16 utility_process_name = |
| 65 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_COMPONENT_PATCHER_NAME); |
| 66 |
| 67 utility_process_mojo_client_.reset( |
| 68 new content::UtilityProcessMojoClient<chrome::mojom::FilePatcher>( |
| 69 utility_process_name)); |
| 70 utility_process_mojo_client_->set_error_callback( |
| 71 base::Bind(&ChromeOutOfProcessPatcher::PatchDone, this, -1)); |
| 72 |
| 73 utility_process_mojo_client_->Start(); // Start the utility process. |
| 74 |
118 if (operation == update_client::kBsdiff) { | 75 if (operation == update_client::kBsdiff) { |
119 patch_message.reset(new ChromeUtilityMsg_PatchFileBsdiff( | 76 utility_process_mojo_client_->service()->PatchFileBsdiff( |
120 input, patch, output)); | 77 std::move(input_file), std::move(patch_file), std::move(output_file), |
| 78 base::Bind(&ChromeOutOfProcessPatcher::PatchDone, this)); |
121 } else if (operation == update_client::kCourgette) { | 79 } else if (operation == update_client::kCourgette) { |
122 patch_message.reset(new ChromeUtilityMsg_PatchFileCourgette( | 80 utility_process_mojo_client_->service()->PatchFileCourgette( |
123 input, patch, output)); | 81 std::move(input_file), std::move(patch_file), std::move(output_file), |
| 82 base::Bind(&ChromeOutOfProcessPatcher::PatchDone, this)); |
124 } else { | 83 } else { |
125 NOTREACHED(); | 84 NOTREACHED(); |
126 } | 85 } |
| 86 } |
127 | 87 |
128 content::BrowserThread::PostTask( | 88 void ChromeOutOfProcessPatcher::PatchDone(int result) { |
129 content::BrowserThread::IO, | 89 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
130 FROM_HERE, | 90 |
131 base::Bind( | 91 utility_process_mojo_client_.reset(); // Terminate the utility process. |
132 &PatchHost::StartProcess, host_, base::Passed(&patch_message))); | 92 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result)); |
133 } | 93 } |
134 | 94 |
135 } // namespace component_updater | 95 } // namespace component_updater |
OLD | NEW |