Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: chrome/browser/downgrade/user_data_downgrade.cc

Issue 1986823002: Reset user data directory and disk cache directory after downgrade. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: browser_tests Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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/browser/downgrade/user_data_downgrade.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/time/time.h"
19 #include "base/version.h"
20 #include "base/win/registry.h"
21 #include "chrome/browser/policy/policy_path_parser.h"
22 #include "chrome/common/chrome_constants.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/chrome_version.h"
26 #include "chrome/installer/util/install_util.h"
27 #include "content/public/browser/browser_thread.h"
28
29 namespace {
30
31 constexpr base::FilePath::CharType g_delete_suffix[] =
32 FILE_PATH_LITERAL(".CHROME_DELETE");
33 bool g_is_browser_test = false;
34
35 // Return the disk cache dir override value if exists or empty path for default
36 // disk cache dir.
37 base::FilePath GetDiskCacheDir() {
38 base::FilePath disk_cache_dir;
39 policy::path_parser::CheckDiskCacheDirPolicy(&disk_cache_dir);
40 if (disk_cache_dir.empty()) {
41 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
42 disk_cache_dir = command_line->GetSwitchValuePath(switches::kDiskCacheDir);
43 }
44 if (disk_cache_dir.ReferencesParent())
45 return base::MakeAbsoluteFilePath(disk_cache_dir);
46 return disk_cache_dir;
47 }
48
49 base::FilePath GetLastChromeVersionFile(const base::FilePath& user_data_dir) {
50 const base::FilePath::StringType last_chrome_version =
51 FILE_PATH_LITERAL("Last Chrome Version");
52 return user_data_dir.Append(last_chrome_version);
53 }
54
55 base::Version GetLastChromeVersion(const base::FilePath& user_data_dir) {
56 std::string last_chrome_version_str;
57 if (base::ReadFileToString(GetLastChromeVersionFile(user_data_dir),
58 &last_chrome_version_str)) {
59 return base::Version(
60 base::TrimWhitespaceASCII(last_chrome_version_str, base::TRIM_ALL)
61 .as_string());
62 }
63 return base::Version();
64 }
65
66 // Return the temporary path that |source_path| will be renamed to later.
67 base::FilePath GetTempDirNameForDelete(const base::FilePath& source_path) {
68 if (source_path.empty())
69 return base::FilePath();
70
71 base::FilePath target_path(source_path.AddExtension(g_delete_suffix));
72 int uniquifier = base::GetUniquePathNumber(source_path, g_delete_suffix);
73 if (uniquifier < 0)
74 return base::FilePath();
75 if (uniquifier > 0) {
76 return target_path.InsertBeforeExtensionASCII(
77 base::StringPrintf(" (%d)", uniquifier));
78 }
79
80 return target_path;
81 }
82
83 // Rename the |source| directory to |target|. Create |source| directory after
84 // rename if |recreate| is true.
85 void RenameDirectory(const base::FilePath& source,
86 const base::FilePath& target,
87 bool recreate) {
88 if (!source.empty() && !target.empty() && base::Move(source, target) &&
89 recreate) {
90 base::CreateDirectory(source);
91 }
92 }
93
94 void DeleteAllRenamedUserDirectories(const base::FilePath& path) {
95 if (path.empty())
96 return;
97 base::FilePath dir_name = path.DirName();
98 // Does not support root directory
99 if (dir_name == path)
100 return;
101
102 base::FilePath::StringType pattern =
103 path.BaseName().value() + FILE_PATH_LITERAL("*") + g_delete_suffix;
104 base::FileEnumerator enumerator(dir_name, false,
105 base::FileEnumerator::DIRECTORIES, pattern);
106 for (base::FilePath dir = enumerator.Next(); !dir.empty();
107 dir = enumerator.Next()) {
108 base::DeleteFile(dir, true);
109 }
110 }
111
112 void DeleteMovedUserData() {
113 base::FilePath user_data_dir;
114 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
115 DeleteAllRenamedUserDirectories(user_data_dir);
116 DeleteAllRenamedUserDirectories(GetDiskCacheDir());
117 }
118
119 } // namespace
120
121 void MoveUserDataForFirstRunAfterDowngrade() {
122 base::FilePath user_data_dir;
123 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
124 base::Version current_version(chrome::kChromeVersion);
125 base::FilePath cur_chrome_exe;
126 if (!PathService::Get(base::FILE_EXE, &cur_chrome_exe))
127 return;
128 // Avoid registry access for browser test.
129 if (g_is_browser_test ||
130 InstallUtil::GetDowngradeVersion(
131 !InstallUtil::IsPerUserInstall(cur_chrome_exe),
132 BrowserDistribution::GetDistribution()) > current_version) {
133 base::FilePath disk_cache_dir(GetDiskCacheDir());
134 // Without the browser process singleton protection, the directory may be
135 // copied multiple times. In order to prevent that from happening, the temp
136 // directory's name will be computed before the LastChromeVersion file is
137 // read. Because the deletion will be scheduled after the singleton is
138 // acquired, the directory can only be moved twice in the worst case.
139 // Also, doing this after the downgrade version check to reduce performance
140 // cost for the normal launch.
141 base::FilePath temp_disk_cache_dir(GetTempDirNameForDelete(disk_cache_dir));
142 base::FilePath temp_user_data_dir(GetTempDirNameForDelete(user_data_dir));
143 if (GetLastChromeVersion(user_data_dir) > current_version) {
144 // Do not recreate |disk_cache_dir| as it will be initialized later.
145 RenameDirectory(disk_cache_dir, temp_disk_cache_dir, false);
146 RenameDirectory(user_data_dir, temp_user_data_dir, true);
147 }
148 }
149 base::WriteFile(GetLastChromeVersionFile(user_data_dir),
150 chrome::kChromeVersion, strlen(chrome::kChromeVersion));
151 }
152
153 void DeleteMovedUserDataSoon() {
154 if (g_is_browser_test) {
grt (UTC plus 2) 2016/05/27 16:26:28 is it possible to get the browser test into "after
zmin 2016/05/27 17:43:00 The after_startup_task will be executed sometimes.
grt (UTC plus 2) 2016/05/27 18:03:00 What if the test posts its own AfterStartupTask an
155 // Delete task will always be executed for browser test.
156 content::BrowserThread::PostBlockingPoolTask(
157 FROM_HERE, base::Bind(&DeleteMovedUserData));
158 } else {
159 content::BrowserThread::PostAfterStartupTask(
160 FROM_HERE, content::BrowserThread::GetBlockingPool(),
161 base::Bind(&DeleteMovedUserData));
162 }
163 }
164
165 void EnableBrowserTest() {
166 g_is_browser_test = true;
167 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698