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