logging_installer.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 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             file_util::PathExists(log_file))) {
63          result = LOGFILE_TRUNCATED;
64        }
65      }
66    } else if (base::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::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
108void EndInstallerLogging() {
109  logging::CloseLogFile();
110
111  installer_logging_ = false;
112}
113
114base::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