1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_NET_LOG_NET_EXPORT_FILE_WRITER_H_
#define COMPONENTS_NET_LOG_NET_EXPORT_FILE_WRITER_H_
#include <memory>
#include <string>
#include "base/command_line.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/log/net_log_capture_mode.h"
#include "services/network/public/mojom/network_service.mojom.h"
namespace base {
class TaskRunner;
} // namespace base
namespace network {
namespace mojom {
class NetworkContext;
}
} // namespace network
namespace net_log {
// NetExportFileWriter is used exclusively as a support class for
// chrome://net-export/. There's a single instance created globally that acts as
// the interface to all NetExportMessageHandlers which can tell it to start or
// stop logging in response to user actions from chrome://net-export/ UIs.
// Because there's only one instance, the logging state can be shared between
// multiple instances of the chrome://net-export/ UI. Internally, it manages a
// pipe to an instance of network::NetLogExporter and handles the
// attaching/detaching of it to the NetLog. This class is used by the iOS and
// non-iOS implementations of chrome://net-export/.
//
// NetExportFileWriter maintains the current logging state using the members
// |state_|, |log_exists_|, |log_capture_mode_known_|, |log_capture_mode_|.
// Its three main commands are Initialize(), StartNetLog(), and StopNetLog().
// These are the only functions that may cause NetExportFileWriter to change
// state. Initialize() must be called before NetExportFileWriter can process any
// other commands. A portion of the initialization needs to run on the
// |file_task_runner_|.
//
// This class is created and destroyed on the UI thread, and all public entry
// points are to be called on the UI thread. Internally, the class may run some
// code on the |file_task_runner_|.
class NetExportFileWriter {
public:
// Special value meaning "can use an unlimited number of bytes".
static constexpr uint64_t kNoLimit =
network::mojom::NetLogExporter::kUnlimitedFileSize;
// The observer interface to be implemented by code that wishes to be notified
// of NetExportFileWriter's state changes.
class StateObserver {
public:
virtual void OnNewState(const base::Value::Dict& state) = 0;
};
// Struct used to store the results of setting up the default log directory
// and log path.
struct DefaultLogPathResults {
bool default_log_path_success;
base::FilePath default_log_path;
bool log_exists;
};
using FilePathCallback = base::OnceCallback<void(const base::FilePath&)>;
using DirectoryGetter = base::RepeatingCallback<bool(base::FilePath*)>;
// Constructs a NetExportFileWriter. Only one instance is created in browser
// process.
NetExportFileWriter();
NetExportFileWriter(const NetExportFileWriter&) = delete;
NetExportFileWriter& operator=(const NetExportFileWriter&) = delete;
~NetExportFileWriter();
// Attaches a StateObserver. |observer| will be notified of state changes to
// NetExportFileWriter. State changes may occur in response to Initiailze(),
// StartNetLog(), or StopNetLog(). StateObserver::OnNewState() will be called
// asynchronously relative to the command that caused the state change.
// |observer| must remain alive until RemoveObserver() is called.
void AddObserver(StateObserver* observer);
// Detaches a StateObserver.
void RemoveObserver(StateObserver* observer);
// Initializes NetExportFileWriter if not initialized. Calling this function
// again is OK.
void Initialize();
// Starts collecting NetLog data into the file at |log_path|. If |log_path| is
// empty, the default log path is used. If NetExportFileWriter is already
// logging, this is a no-op and |capture_mode| is ignored.
//
// |max_file_size| places a bound on how large the log file can grow. To make
// it grow unboundedly pass kNoLimit.
//
// |network_context| will be used to append net info (from net::GetInfo())
// at end of logging once StopNetLog is called.
void StartNetLog(const base::FilePath& log_path,
net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
const base::CommandLine::StringType& command_line_string,
const std::string& channel_string,
network::mojom::NetworkContext* network_context);
// Stops collecting NetLog data into the file. It is a no-op if
// NetExportFileWriter is currently not logging.
//
// |polled_data| is a JSON dictionary that will be appended to the end of the
// log; it's for adding additional info to the log that aren't events.
void StopNetLog(base::Value::Dict polled_data = base::Value::Dict());
// Creates a `base::Value::Dict` summary of the state of the
// `NetExportFileWriter`.
base::Value::Dict GetState() const;
// Gets the log filepath. |path_callback| will be used to notify the caller
// when the filepath is retrieved. |path_callback| will be executed with an
// empty filepath if any of the following occurs:
// (1) The NetExportFileWriter is not initialized.
// (2) The log file does not exist.
// (3) The NetExportFileWriter is currently logging.
//
// |path_callback| will be executed at the end of GetFilePathToCompletedLog()
// asynchronously.
void GetFilePathToCompletedLog(FilePathCallback path_callback) const;
// Converts to/from the string representation of a capture mode used by
// net_export.js.
static std::string CaptureModeToString(net::NetLogCaptureMode capture_mode);
static net::NetLogCaptureMode CaptureModeFromString(
const std::string& capture_mode_string);
// Overrides the getter used to retrieve the default log base directory during
// initialization. Should only be used by unit tests.
void SetDefaultLogBaseDirectoryGetterForTest(const DirectoryGetter& getter);
private:
friend class NetExportFileWriterTest;
// The possible logging states of NetExportFileWriter.
enum State {
STATE_UNINITIALIZED,
// Currently in the process of initializing.
STATE_INITIALIZING,
// Not currently logging to file.
STATE_NOT_LOGGING,
// Currently in the process of starting the log.
STATE_STARTING_LOG,
// Currently logging to file.
STATE_LOGGING,
// Currently in the process of stopping the log.
STATE_STOPPING_LOG,
};
void NotifyStateObservers();
// Posts NotifyStateObservers() to the current thread.
void NotifyStateObserversAsync();
// Called internally by Initialize(). Will initialize NetExportFileWriter's
// state variables after the default log directory is set up and the default
// log path is determined on the |file_task_runner_|.
void SetStateAfterSetUpDefaultLogPath(
const DefaultLogPathResults& set_up_default_log_path_results);
// Called internally by StartNetLog(). Contains tasks to be done to start
// logging after the output file has been created.
void StartNetLogAfterCreateFile(net::NetLogCaptureMode capture_mode,
uint64_t max_file_size,
base::Value::Dict custom_constants,
base::File log_file);
void OnStartResult(net::NetLogCaptureMode capture_mode, int result);
void OnStopResult(int result);
void OnConnectionError();
// Contains tasks to be done after |net_log_exporter_| has completely
// stopped writing.
void ResetExporterThenSetStateNotLogging();
// Creates a new file for writing at |path|, trying to overwrite any existing
// file. Called on |file_task_runner_|.
static base::File CreateOutputFile(base::FilePath path);
// All members are accessed solely from the main thread (the thread that
// |thread_checker_| is bound to).
base::ThreadChecker thread_checker_;
// Task runners for file-specific and net-specific tasks that must run on a
// file or net task runner.
scoped_refptr<base::TaskRunner> file_task_runner_;
State state_; // Current logging state of NetExportFileWriter.
bool log_exists_; // Whether or not a log file exists on disk.
bool log_capture_mode_known_;
net::NetLogCaptureMode log_capture_mode_;
base::FilePath log_path_; // base::FilePath to the NetLog file.
// Used to ask the network service to do the actual exporting.
mojo::Remote<network::mojom::NetLogExporter> net_log_exporter_;
// List of StateObservers to notify on state changes.
base::ObserverList<StateObserver, true>::Unchecked state_observer_list_;
// Used by unit tests to override the default log base directory retrieved
// during initialization. This getter is initialized to base::GetTempDir().
DirectoryGetter default_log_base_dir_getter_;
base::WeakPtrFactory<NetExportFileWriter> weak_ptr_factory_{this};
};
} // namespace net_log
#endif // COMPONENTS_NET_LOG_NET_EXPORT_FILE_WRITER_H_
|