- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / self_cleaning_temp_dir.cc
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/self_cleaning_temp_dir.h"
6
7 #include <windows.h>
8
9 #include "base/file_util.h"
10 #include "base/logging.h"
11 #include "chrome/installer/util/delete_after_reboot_helper.h"
12
13 namespace installer {
14
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);
23
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();
36   }
37 }
38
39 SelfCleaningTempDir::SelfCleaningTempDir() {
40 }
41
42 SelfCleaningTempDir::~SelfCleaningTempDir() {
43   if (!path().empty() && !Delete())
44     LOG(WARNING) << "Failed to clean temp dir in dtor " << path().value();
45 }
46
47 bool SelfCleaningTempDir::Initialize(const base::FilePath& parent_dir,
48                                      const StringType& temp_name) {
49   DCHECK(parent_dir.IsAbsolute());
50   DCHECK(!temp_name.empty());
51
52   if (!path().empty()) {
53     LOG(DFATAL) << "Attempting to re-initialize a SelfSelfCleaningTempDir.";
54     return false;
55   }
56
57   base::FilePath temp_dir(parent_dir.Append(temp_name));
58   base::FilePath base_dir;
59   GetTopDirToCreate(parent_dir, &base_dir);
60
61   if (file_util::CreateDirectory(temp_dir)) {
62     base_dir_ = base_dir;
63     temp_dir_ = temp_dir;
64     return true;
65   }
66
67   return false;
68 }
69
70 bool SelfCleaningTempDir::Delete() {
71   if (path().empty()) {
72     LOG(DFATAL) << "Attempting to Delete an uninitialized SelfCleaningTempDir.";
73     return false;
74   }
75
76   base::FilePath next_dir(path().DirName());
77   bool schedule_deletes = false;
78
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).
89   }
90
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;
100       }
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);
105       }
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);
110   }
111
112   base_dir_.clear();
113   temp_dir_.clear();
114
115   return true;
116 }
117
118 }  // namespace installer