Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / installer / util / self_cleaning_temp_dir.cc
blob19697bbe72f5ca1bf6c8a55cf34f30f615124d6c
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.
5 #include "chrome/installer/util/self_cleaning_temp_dir.h"
7 #include <windows.h>
9 #include "base/files/file_util.h"
10 #include "base/logging.h"
11 #include "chrome/installer/util/delete_after_reboot_helper.h"
13 namespace installer {
15 // Populates |base_dir| with the topmost directory in the hierarchy of
16 // |temp_parent_dir| that does not exist. If |temp_parent_dir| exists,
17 // |base_dir| is cleared.
18 // static
19 void SelfCleaningTempDir::GetTopDirToCreate(
20 const base::FilePath& temp_parent_dir,
21 base::FilePath* base_dir) {
22 DCHECK(base_dir);
24 if (base::PathExists(temp_parent_dir)) {
25 // Empty base_dir means that we didn't create any extra directories.
26 base_dir->clear();
27 } else {
28 base::FilePath parent_dir(temp_parent_dir);
29 do {
30 *base_dir = parent_dir;
31 parent_dir = parent_dir.DirName();
32 } while (parent_dir != *base_dir && !base::PathExists(parent_dir));
33 LOG_IF(WARNING, !base::DirectoryExists(parent_dir))
34 << "A non-directory is at the base of the path leading to a desired "
35 "temp directory location: " << parent_dir.value();
39 SelfCleaningTempDir::SelfCleaningTempDir() {
42 SelfCleaningTempDir::~SelfCleaningTempDir() {
43 if (!path().empty() && !Delete())
44 LOG(WARNING) << "Failed to clean temp dir in dtor " << path().value();
47 bool SelfCleaningTempDir::Initialize(const base::FilePath& parent_dir,
48 const StringType& temp_name) {
49 DCHECK(parent_dir.IsAbsolute());
50 DCHECK(!temp_name.empty());
52 if (!path().empty()) {
53 LOG(DFATAL) << "Attempting to re-initialize a SelfSelfCleaningTempDir.";
54 return false;
57 base::FilePath temp_dir(parent_dir.Append(temp_name));
58 base::FilePath base_dir;
59 GetTopDirToCreate(parent_dir, &base_dir);
61 if (base::CreateDirectory(temp_dir)) {
62 base_dir_ = base_dir;
63 temp_dir_ = temp_dir;
64 return true;
67 return false;
70 bool SelfCleaningTempDir::Delete() {
71 if (path().empty()) {
72 LOG(DFATAL) << "Attempting to Delete an uninitialized SelfCleaningTempDir.";
73 return false;
76 base::FilePath next_dir(path().DirName());
77 bool schedule_deletes = false;
79 // First try to recursively delete the leaf directory managed by our
80 // base::ScopedTempDir.
81 if (!base::DeleteFile(path(), true)) {
82 // That failed, so schedule the temp dir and its contents for deletion after
83 // reboot.
84 LOG(WARNING) << "Failed to delete temporary directory " << path().value()
85 << ". Scheduling for deletion at reboot.";
86 schedule_deletes = true;
87 if (!ScheduleDirectoryForDeletion(path()))
88 return false; // Entirely unexpected failure (Schedule logs the reason).
91 // Now delete or schedule all empty directories up to and including our
92 // base_dir_. Any that can't be deleted are scheduled for deletion at reboot.
93 // This is safe since they'll only be deleted in that case if they're empty.
94 if (!base_dir_.empty()) {
95 do {
96 if (!schedule_deletes && !RemoveDirectory(next_dir.value().c_str())) {
97 PLOG_IF(WARNING, GetLastError() != ERROR_DIR_NOT_EMPTY)
98 << "Error removing directory " << next_dir.value().c_str();
99 schedule_deletes = true;
101 if (schedule_deletes) {
102 // Ignore the return code. If we fail to schedule, go ahead and add the
103 // other parent directories anyway.
104 ScheduleFileSystemEntityForDeletion(next_dir);
106 if (next_dir == base_dir_)
107 break; // We just processed the topmost directory we created.
108 next_dir = next_dir.DirName();
109 } while (true);
112 base_dir_.clear();
113 temp_dir_.clear();
115 return true;
118 } // namespace installer