logging_installer.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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}
24static const GUID kSetupTraceProvider = { 0x93bce0bf, 0x3faf, 0x43b1,
25    { 0x9e, 0x28, 0xbe, 0xb6, 0xfa, 0xb5, 0xec, 0xe7 } };
26
27namespace installer {
28
29// This should be true for the period between the end of
30// InitInstallerLogging() and the beginning of EndInstallerLogging().
31bool installer_logging_ = false;
32
33TruncateResult 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 file_util::Move will attempt to replace existing files.
51      if (file_util::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             file_util::PathExists(log_file))) {
63          result = LOGFILE_TRUNCATED;
64        }
65      }
66    } else if (file_util::Delete(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
77void 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::InitLogging(
93      log_file_path.value().c_str(),
94      logging::LOG_ONLY_TO_FILE,
95      logging::LOCK_LOG_FILE,
96      logging::APPEND_TO_OLD_LOG_FILE,
97      logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
98
99  if (prefs.GetBool(installer::master_preferences::kVerboseLogging,
100                    &value) && value) {
101    logging::SetMinLogLevel(logging::LOG_VERBOSE);
102  } else {
103    logging::SetMinLogLevel(logging::LOG_ERROR);
104  }
105
106  // Enable ETW logging.
107  logging::LogEventProvider::Initialize(kSetupTraceProvider);
108}
109
110void EndInstallerLogging() {
111  logging::CloseLogFile();
112
113  installer_logging_ = false;
114}
115
116base::FilePath GetLogFilePath(const installer::MasterPreferences& prefs) {
117  std::string path;
118  prefs.GetString(installer::master_preferences::kLogFile, &path);
119  if (!path.empty()) {
120    return base::FilePath(UTF8ToWide(path));
121  }
122
123  std::wstring log_filename = prefs.install_chrome_frame() ?
124      L"chrome_frame_installer.log" : L"chrome_installer.log";
125
126  base::FilePath log_path;
127  if (PathService::Get(base::DIR_TEMP, &log_path)) {
128    log_path = log_path.Append(log_filename);
129    return log_path;
130  } else {
131    return base::FilePath(log_filename);
132  }
133}
134
135}  // namespace installer
136