- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / create_reg_key_work_item.cc
1 // Copyright (c) 2010 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 <shlwapi.h>
6
7 #include "base/files/file_path.h"
8 #include "base/logging.h"
9 #include "base/win/registry.h"
10 #include "chrome/installer/util/create_reg_key_work_item.h"
11 #include "chrome/installer/util/install_util.h"
12 #include "chrome/installer/util/logging_installer.h"
13
14 using base::win::RegKey;
15
16 namespace {
17
18 // TODO: refactor this because it is only used once.
19 void UpOneDirectoryOrEmpty(std::wstring* dir) {
20   base::FilePath path = base::FilePath(*dir);
21   base::FilePath directory = path.DirName();
22   // If there is no separator, we will get back kCurrentDirectory.
23   // In this case, clear dir.
24   if (directory == path || directory.value() ==
25       base::FilePath::kCurrentDirectory)
26     dir->clear();
27   else
28     *dir = directory.value();
29 }
30
31 }  // namespace
32
33 CreateRegKeyWorkItem::~CreateRegKeyWorkItem() {
34 }
35
36 CreateRegKeyWorkItem::CreateRegKeyWorkItem(HKEY predefined_root,
37                                            const std::wstring& path)
38     : predefined_root_(predefined_root),
39       path_(path),
40       key_created_(false) {
41 }
42
43 bool CreateRegKeyWorkItem::Do() {
44   if (!InitKeyList()) {
45     // Nothing needs to be done here.
46     VLOG(1) << "no key to create";
47     return true;
48   }
49
50   RegKey key;
51   std::wstring key_path;
52
53   // To create keys, we iterate from back to front.
54   for (size_t i = key_list_.size(); i > 0; i--) {
55     DWORD disposition;
56     key_path.assign(key_list_[i - 1]);
57
58     if (key.CreateWithDisposition(predefined_root_, key_path.c_str(),
59                                   &disposition, KEY_READ) == ERROR_SUCCESS) {
60       if (disposition == REG_OPENED_EXISTING_KEY) {
61         if (key_created_) {
62           // This should not happen. Someone created a subkey under the key
63           // we just created?
64           LOG(ERROR) << key_path << " exists, this is not expected.";
65           return false;
66         }
67         // Remove the key path from list if it is already present.
68         key_list_.pop_back();
69       } else if (disposition == REG_CREATED_NEW_KEY) {
70         VLOG(1) << "created " << key_path;
71         key_created_ = true;
72       } else {
73         LOG(ERROR) << "unkown disposition";
74         return false;
75       }
76     } else {
77       LOG(ERROR) << "Failed to create " << key_path;
78       return false;
79     }
80   }
81
82   return true;
83 }
84
85 void CreateRegKeyWorkItem::Rollback() {
86   if (!key_created_)
87     return;
88
89   std::wstring key_path;
90   // To delete keys, we iterate from front to back.
91   std::vector<std::wstring>::iterator itr;
92   for (itr = key_list_.begin(); itr != key_list_.end(); ++itr) {
93     key_path.assign(*itr);
94     if (SHDeleteEmptyKey(predefined_root_, key_path.c_str()) ==
95         ERROR_SUCCESS) {
96       VLOG(1) << "rollback: delete " << key_path;
97     } else {
98       VLOG(1) << "rollback: can not delete " << key_path;
99       // The key might have been deleted, but we don't reliably know what
100       // error code(s) are returned in this case. So we just keep tring delete
101       // the rest.
102     }
103   }
104
105   key_created_ = false;
106   key_list_.clear();
107   return;
108 }
109
110 bool CreateRegKeyWorkItem::InitKeyList() {
111   if (path_.empty())
112     return false;
113
114   std::wstring key_path(path_);
115
116   do {
117     key_list_.push_back(key_path);
118     // This is pure string operation so it does not matter whether the
119     // path is file path or registry path.
120     UpOneDirectoryOrEmpty(&key_path);
121   } while (!key_path.empty());
122
123   return true;
124 }