1// Copyright (c) 2011 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/installer/util/work_item_list.h"
6
7#include "base/files/file_path.h"
8#include "base/logging.h"
9#include "chrome/installer/util/callback_work_item.h"
10#include "chrome/installer/util/copy_tree_work_item.h"
11#include "chrome/installer/util/create_dir_work_item.h"
12#include "chrome/installer/util/create_reg_key_work_item.h"
13#include "chrome/installer/util/delete_reg_key_work_item.h"
14#include "chrome/installer/util/delete_reg_value_work_item.h"
15#include "chrome/installer/util/delete_tree_work_item.h"
16#include "chrome/installer/util/logging_installer.h"
17#include "chrome/installer/util/move_tree_work_item.h"
18#include "chrome/installer/util/self_reg_work_item.h"
19#include "chrome/installer/util/set_reg_value_work_item.h"
20
21WorkItemList::~WorkItemList() {
22  for (WorkItemIterator itr = list_.begin(); itr != list_.end(); ++itr) {
23    delete (*itr);
24  }
25  for (WorkItemIterator itr = executed_list_.begin();
26       itr != executed_list_.end(); ++itr) {
27    delete (*itr);
28  }
29}
30
31WorkItemList::WorkItemList()
32    : status_(ADD_ITEM) {
33}
34
35bool WorkItemList::Do() {
36  if (status_ != ADD_ITEM)
37    return false;
38
39  bool result = true;
40  while (!list_.empty()) {
41    WorkItem* work_item = list_.front();
42    list_.pop_front();
43    executed_list_.push_front(work_item);
44    if (!work_item->Do()) {
45      LOG(ERROR) << "item execution failed " << work_item->log_message();
46      result = false;
47      break;
48    }
49  }
50
51  if (result)
52    VLOG(1) << "list execution succeeded";
53
54  status_ = LIST_EXECUTED;
55  return result;
56}
57
58void WorkItemList::Rollback() {
59  if (status_ != LIST_EXECUTED)
60    return;
61
62  for (WorkItemIterator itr = executed_list_.begin();
63       itr != executed_list_.end(); ++itr) {
64    (*itr)->Rollback();
65  }
66
67  status_ = LIST_ROLLED_BACK;
68  return;
69}
70
71void WorkItemList::AddWorkItem(WorkItem* work_item) {
72  DCHECK(status_ == ADD_ITEM);
73  list_.push_back(work_item);
74}
75
76WorkItem* WorkItemList::AddCallbackWorkItem(
77    base::Callback<bool(const CallbackWorkItem&)> callback) {
78  WorkItem* item = WorkItem::CreateCallbackWorkItem(callback);
79  AddWorkItem(item);
80  return item;
81}
82
83WorkItem* WorkItemList::AddCopyTreeWorkItem(
84    const std::wstring& source_path,
85    const std::wstring& dest_path,
86    const std::wstring& temp_dir,
87    CopyOverWriteOption overwrite_option,
88    const std::wstring& alternative_path) {
89  WorkItem* item = WorkItem::CreateCopyTreeWorkItem(
90      base::FilePath(source_path),
91      base::FilePath(dest_path),
92      base::FilePath(temp_dir),
93      overwrite_option,
94      base::FilePath(alternative_path));
95  AddWorkItem(item);
96  return item;
97}
98
99WorkItem* WorkItemList::AddCreateDirWorkItem(const base::FilePath& path) {
100  WorkItem* item = WorkItem::CreateCreateDirWorkItem(path);
101  AddWorkItem(item);
102  return item;
103}
104
105WorkItem* WorkItemList::AddCreateRegKeyWorkItem(HKEY predefined_root,
106                                                const std::wstring& path,
107                                                REGSAM wow64_access) {
108  WorkItem* item =
109      WorkItem::CreateCreateRegKeyWorkItem(predefined_root, path, wow64_access);
110  AddWorkItem(item);
111  return item;
112}
113
114WorkItem* WorkItemList::AddDeleteRegKeyWorkItem(HKEY predefined_root,
115                                                const std::wstring& path,
116                                                REGSAM wow64_access) {
117  WorkItem* item =
118      WorkItem::CreateDeleteRegKeyWorkItem(predefined_root, path, wow64_access);
119  AddWorkItem(item);
120  return item;
121}
122
123WorkItem* WorkItemList::AddDeleteRegValueWorkItem(
124    HKEY predefined_root,
125    const std::wstring& key_path,
126    REGSAM wow64_access,
127    const std::wstring& value_name) {
128  WorkItem* item = WorkItem::CreateDeleteRegValueWorkItem(
129      predefined_root, key_path, wow64_access, value_name);
130  AddWorkItem(item);
131  return item;
132}
133
134WorkItem* WorkItemList::AddDeleteTreeWorkItem(
135    const base::FilePath& root_path,
136    const base::FilePath& temp_path,
137    const std::vector<base::FilePath>& key_paths) {
138  WorkItem* item = WorkItem::CreateDeleteTreeWorkItem(root_path, temp_path,
139                                                      key_paths);
140  AddWorkItem(item);
141  return item;
142}
143
144WorkItem* WorkItemList::AddDeleteTreeWorkItem(const base::FilePath& root_path,
145                                              const base::FilePath& temp_path) {
146  std::vector<base::FilePath> no_key_files;
147  return AddDeleteTreeWorkItem(root_path, temp_path, no_key_files);
148}
149
150WorkItem* WorkItemList::AddMoveTreeWorkItem(const std::wstring& source_path,
151                                            const std::wstring& dest_path,
152                                            const std::wstring& temp_dir,
153                                            MoveTreeOption duplicate_option) {
154  WorkItem* item = WorkItem::CreateMoveTreeWorkItem(base::FilePath(source_path),
155                                                    base::FilePath(dest_path),
156                                                    base::FilePath(temp_dir),
157                                                    duplicate_option);
158  AddWorkItem(item);
159  return item;
160}
161
162WorkItem* WorkItemList::AddSetRegValueWorkItem(HKEY predefined_root,
163                                               const std::wstring& key_path,
164                                               REGSAM wow64_access,
165                                               const std::wstring& value_name,
166                                               const std::wstring& value_data,
167                                               bool overwrite) {
168  WorkItem* item = WorkItem::CreateSetRegValueWorkItem(predefined_root,
169                                                       key_path,
170                                                       wow64_access,
171                                                       value_name,
172                                                       value_data,
173                                                       overwrite);
174  AddWorkItem(item);
175  return item;
176}
177
178WorkItem* WorkItemList::AddSetRegValueWorkItem(HKEY predefined_root,
179                                               const std::wstring& key_path,
180                                               REGSAM wow64_access,
181                                               const std::wstring& value_name,
182                                               DWORD value_data,
183                                               bool overwrite) {
184  WorkItem* item = WorkItem::CreateSetRegValueWorkItem(predefined_root,
185                                                       key_path,
186                                                       wow64_access,
187                                                       value_name,
188                                                       value_data,
189                                                       overwrite);
190  AddWorkItem(item);
191  return item;
192}
193
194WorkItem* WorkItemList::AddSetRegValueWorkItem(HKEY predefined_root,
195                                               const std::wstring& key_path,
196                                               REGSAM wow64_access,
197                                               const std::wstring& value_name,
198                                               int64 value_data,
199                                               bool overwrite) {
200  WorkItem* item = reinterpret_cast<WorkItem*>(
201      WorkItem::CreateSetRegValueWorkItem(predefined_root,
202                                          key_path,
203                                          wow64_access,
204                                          value_name,
205                                          value_data,
206                                          overwrite));
207  AddWorkItem(item);
208  return item;
209}
210
211WorkItem* WorkItemList::AddSelfRegWorkItem(const std::wstring& dll_path,
212                                           bool do_register,
213                                           bool user_level_registration) {
214  WorkItem* item = WorkItem::CreateSelfRegWorkItem(dll_path, do_register,
215                                                   user_level_registration);
216  AddWorkItem(item);
217  return item;
218}
219
220////////////////////////////////////////////////////////////////////////////////
221NoRollbackWorkItemList::~NoRollbackWorkItemList() {
222}
223
224bool NoRollbackWorkItemList::Do() {
225  if (status_ != ADD_ITEM)
226    return false;
227
228  bool result = true;
229  while (!list_.empty()) {
230    WorkItem* work_item = list_.front();
231    list_.pop_front();
232    executed_list_.push_front(work_item);
233    work_item->set_ignore_failure(true);
234    if (!work_item->Do()) {
235      LOG(ERROR) << "NoRollbackWorkItemList: item execution failed "
236                 << work_item->log_message();
237      result = false;
238    }
239  }
240
241  if (result)
242    VLOG(1) << "NoRollbackWorkItemList: list execution succeeded";
243
244  status_ = LIST_EXECUTED;
245  return result;
246}
247
248void NoRollbackWorkItemList::Rollback() {
249  // Ignore rollback.
250}
251