1 // Copyright 2013 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/profiles/file_path_verifier_win.h" 6 7 #include <windows.h> 8 9 #include "base/file_util.h" 10 #include "base/files/file_path.h" 11 #include "base/metrics/histogram.h" 12 #include "chrome_elf/create_file/chrome_create_file.h" 13 14 namespace { 15 16 // This enum is used in UMA histograms and should never be re-ordered. 17 enum FileVerificationResult { 18 FILE_VERIFICATION_SUCCESS, 19 FILE_VERIFICATION_FILE_NOT_FOUND, 20 FILE_VERIFICATION_INTERNAL_ERROR, 21 FILE_VERIFICATION_FAILED_UNKNOWN, 22 FILE_VERIFICATION_FAILED_SAMEBASE, 23 FILE_VERIFICATION_FAILED_SAMEDIR, 24 FILE_VERIFICATION_SUCCESS_REDIRECT, 25 FILE_VERIFICATION_FAILED_SAMEBASE_REDIRECT, 26 FILE_VERIFICATION_FAILED_SAMEDIR_REDIRECT, 27 NUM_FILE_VERIFICATION_RESULTS 28 }; 29 30 // Returns a FileVerificationResult based on the state of |file| on disk. 31 FileVerificationResult VerifyFileAtPath(const base::FilePath& file) { 32 FileVerificationResult file_verification_result = 33 FILE_VERIFICATION_FAILED_UNKNOWN; 34 base::FilePath normalized_path; 35 int redirect_count_before = ::GetRedirectCount(); 36 if (!base::NormalizeFilePath(file, &normalized_path)) { 37 if (::GetLastError() == ERROR_FILE_NOT_FOUND) 38 file_verification_result = FILE_VERIFICATION_FILE_NOT_FOUND; 39 else 40 file_verification_result = FILE_VERIFICATION_INTERNAL_ERROR; 41 } else { 42 internal::PathComparisonReason path_comparison_reason = 43 internal::ComparePathsIgnoreCase(file, normalized_path); 44 // GetRedirectCount() tracks the number of CreateFile() calls that were 45 // redirected. If it has increased then the CreateFile() call made by 46 // base::NormalizeFilePath() was redirected. 47 bool was_redirected = ::GetRedirectCount() > redirect_count_before; 48 switch (path_comparison_reason) { 49 case internal::PATH_COMPARISON_EQUAL: 50 file_verification_result = was_redirected ? 51 FILE_VERIFICATION_SUCCESS_REDIRECT : FILE_VERIFICATION_SUCCESS; 52 break; 53 case internal::PATH_COMPARISON_FAILED_SAMEBASE: 54 file_verification_result = was_redirected ? 55 FILE_VERIFICATION_FAILED_SAMEBASE_REDIRECT : 56 FILE_VERIFICATION_FAILED_SAMEBASE; 57 break; 58 case internal::PATH_COMPARISON_FAILED_SAMEDIR: 59 file_verification_result = was_redirected ? 60 FILE_VERIFICATION_FAILED_SAMEDIR_REDIRECT : 61 FILE_VERIFICATION_FAILED_SAMEDIR; 62 break; 63 } 64 } 65 return file_verification_result; 66 } 67 68 } // namespace 69 70 namespace internal { 71 72 PathComparisonReason ComparePathsIgnoreCase(const base::FilePath& path1, 73 const base::FilePath& path2) { 74 PathComparisonReason reason = PATH_COMPARISON_FAILED_UNKNOWN; 75 76 if (base::FilePath::CompareEqualIgnoreCase(path1.value(), path2.value())) { 77 reason = PATH_COMPARISON_EQUAL; 78 } else if (base::FilePath::CompareEqualIgnoreCase(path1.BaseName().value(), 79 path2.BaseName().value())) { 80 reason = PATH_COMPARISON_FAILED_SAMEBASE; 81 } else if (base::FilePath::CompareEqualIgnoreCase(path1.DirName().value(), 82 path2.DirName().value())) { 83 reason = PATH_COMPARISON_FAILED_SAMEDIR; 84 } 85 86 return reason; 87 } 88 89 } // namespace internal 90 91 void VerifyPreferencesFile(const base::FilePath& pref_file_path) { 92 FileVerificationResult file_verification_result = 93 VerifyFileAtPath(pref_file_path); 94 UMA_HISTOGRAM_ENUMERATION("Stability.FileAtPath.Preferences", 95 file_verification_result, 96 NUM_FILE_VERIFICATION_RESULTS); 97 } 98