xref: /aosp_15_r20/external/cronet/base/files/block_tests_writing_to_special_dirs.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 The Chromium Authors
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 "base/files/block_tests_writing_to_special_dirs.h"
6 
7 #include <utility>
8 
9 #include "base/files/file_path.h"
10 #include "base/no_destructor.h"
11 #include "base/path_service.h"
12 
13 namespace base {
14 
15 // static
16 std::optional<BlockTestsWritingToSpecialDirs>&
Get()17 BlockTestsWritingToSpecialDirs::Get() {
18   static NoDestructor<std::optional<BlockTestsWritingToSpecialDirs>>
19       block_tests_writing_to_special_dirs;
20   return *block_tests_writing_to_special_dirs;
21 }
22 
23 // static
CanWriteToPath(const FilePath & path)24 bool BlockTestsWritingToSpecialDirs::CanWriteToPath(const FilePath& path) {
25   auto& dir_blocker = Get();
26   if (!dir_blocker.has_value()) {
27     return true;
28   }
29   if (!dir_blocker->blocked_dirs_.empty()) {
30     // `blocked_paths_` needs to be initialized lazily because PathService::Get
31     // can't be called from the test harness code before the indiviudal tests
32     // run. On Windows, calling PathService::Get in the test harness startup
33     // codel causes user32.dll to get loaded, which breaks  delayload_unittests.
34     // On the Mac, it triggers a change in `AmIBundled`.
35     for (const int dir_key : dir_blocker->blocked_dirs_) {
36       // If test infrastructure has overridden `dir_key` already, there is no
37       // need to block writes to it. Android tests apparently do this.
38       if (PathService::IsOverriddenForTesting(dir_key)) {
39         continue;
40       }
41       FilePath path_to_block;
42       // Sandbox can make PathService::Get fail.
43       if (PathService::Get(dir_key, &path_to_block)) {
44         dir_blocker->blocked_paths_.insert(std::move(path_to_block));
45       }
46     }
47     dir_blocker->blocked_dirs_.clear();
48   }
49   for (const auto& path_to_block : dir_blocker->blocked_paths_) {
50     if (path_to_block.IsParent(path)) {
51       (*dir_blocker->failure_callback_)(path);
52       return false;
53     }
54   }
55   return true;
56 }
57 
BlockTestsWritingToSpecialDirs(std::vector<int> blocked_dirs,FileWriteBlockedForTestingFunctionPtr failure_callback)58 BlockTestsWritingToSpecialDirs::BlockTestsWritingToSpecialDirs(
59     std::vector<int> blocked_dirs,
60     FileWriteBlockedForTestingFunctionPtr failure_callback)
61     : blocked_dirs_(std::move(blocked_dirs)),
62       failure_callback_(failure_callback) {}
63 
64 BlockTestsWritingToSpecialDirs::~BlockTestsWritingToSpecialDirs() = default;
65 
66 }  // namespace base
67