Home | History | Annotate | Download | only in util
      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 <windows.h>
      6 
      7 #include "chrome/installer/util/logging_installer.h"
      8 
      9 #include "base/command_line.h"
     10 #include "base/file_util.h"
     11 #include "base/files/file_path.h"
     12 #include "base/logging.h"
     13 #include "base/logging_win.h"
     14 #include "base/path_service.h"
     15 #include "base/platform_file.h"
     16 #include "base/strings/string_util.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "base/win/scoped_handle.h"
     19 #include "chrome/installer/util/master_preferences.h"
     20 #include "chrome/installer/util/master_preferences_constants.h"
     21 #include "chrome/installer/util/util_constants.h"
     22 
     23 // {93BCE0BF-3FAF-43b1-9E28-BEB6FAB5ECE7}
     24 static const GUID kSetupTraceProvider = { 0x93bce0bf, 0x3faf, 0x43b1,
     25     { 0x9e, 0x28, 0xbe, 0xb6, 0xfa, 0xb5, 0xec, 0xe7 } };
     26 
     27 namespace installer {
     28 
     29 // This should be true for the period between the end of
     30 // InitInstallerLogging() and the beginning of EndInstallerLogging().
     31 bool installer_logging_ = false;
     32 
     33 TruncateResult TruncateLogFileIfNeeded(const base::FilePath& log_file) {
     34   TruncateResult result = LOGFILE_UNTOUCHED;
     35 
     36   int64 log_size = 0;
     37   if (file_util::GetFileSize(log_file, &log_size) &&
     38       log_size > kMaxInstallerLogFileSize) {
     39     // Cause the old log file to be deleted when we are done with it.
     40     const int file_flags = base::PLATFORM_FILE_OPEN |
     41                            base::PLATFORM_FILE_READ |
     42                            base::PLATFORM_FILE_SHARE_DELETE |
     43                            base::PLATFORM_FILE_DELETE_ON_CLOSE;
     44     base::win::ScopedHandle old_log_file(
     45         base::CreatePlatformFile(log_file, file_flags, NULL, NULL));
     46 
     47     if (old_log_file.IsValid()) {
     48       result = LOGFILE_DELETED;
     49       base::FilePath tmp_log(log_file.value() + FILE_PATH_LITERAL(".tmp"));
     50       // Note that base::Move will attempt to replace existing files.
     51       if (base::Move(log_file, tmp_log)) {
     52         int64 offset = log_size - kTruncatedInstallerLogFileSize;
     53         std::string old_log_data(kTruncatedInstallerLogFileSize, 0);
     54         int bytes_read = base::ReadPlatformFile(old_log_file,
     55                                                 offset,
     56                                                 &old_log_data[0],
     57                                                 kTruncatedInstallerLogFileSize);
     58         if (bytes_read > 0 &&
     59             (bytes_read == file_util::WriteFile(log_file,
     60                                                 &old_log_data[0],
     61                                                 bytes_read) ||
     62              base::PathExists(log_file))) {
     63           result = LOGFILE_TRUNCATED;
     64         }
     65       }
     66     } else if (base::DeleteFile(log_file, false)) {
     67       // Couldn't get sufficient access to the log file, optimistically try to
     68       // delete it.
     69       result = LOGFILE_DELETED;
     70     }
     71   }
     72 
     73   return result;
     74 }
     75 
     76 
     77 void InitInstallerLogging(const installer::MasterPreferences& prefs) {
     78   if (installer_logging_)
     79     return;
     80 
     81   installer_logging_ = true;
     82 
     83   bool value = false;
     84   if (prefs.GetBool(installer::master_preferences::kDisableLogging,
     85                     &value) && value) {
     86     return;
     87   }
     88 
     89   base::FilePath log_file_path(GetLogFilePath(prefs));
     90   TruncateLogFileIfNeeded(log_file_path);
     91 
     92   logging::LoggingSettings settings;
     93   settings.logging_dest = logging::LOG_TO_FILE;
     94   settings.log_file = log_file_path.value().c_str();
     95   logging::InitLogging(settings);
     96 
     97   if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
     98                     &value) && value) {
     99     logging::SetMinLogLevel(logging::LOG_VERBOSE);
    100   } else {
    101     logging::SetMinLogLevel(logging::LOG_ERROR);
    102   }
    103 
    104   // Enable ETW logging.
    105   logging::LogEventProvider::Initialize(kSetupTraceProvider);
    106 }
    107 
    108 void EndInstallerLogging() {
    109   logging::CloseLogFile();
    110 
    111   installer_logging_ = false;
    112 }
    113 
    114 base::FilePath GetLogFilePath(const installer::MasterPreferences& prefs) {
    115   std::string path;
    116   prefs.GetString(installer::master_preferences::kLogFile, &path);
    117   if (!path.empty()) {
    118     return base::FilePath(UTF8ToWide(path));
    119   }
    120 
    121   std::wstring log_filename = prefs.install_chrome_frame() ?
    122       L"chrome_frame_installer.log" : L"chrome_installer.log";
    123 
    124   base::FilePath log_path;
    125   if (PathService::Get(base::DIR_TEMP, &log_path)) {
    126     log_path = log_path.Append(log_filename);
    127     return log_path;
    128   } else {
    129     return base::FilePath(log_filename);
    130   }
    131 }
    132 
    133 }  // namespace installer
    134