Home | History | Annotate | Download | only in profiles
      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