Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: components/net_log/net_log_file_writer.h

Issue 2603523002: Move net-export thread-hopping code into NetLogFileWriter and add IO polled data. (Closed)
Patch Set: Fixed nits; callbacks are now always executed regardless of failure or no-op Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_ 5 #ifndef COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_
6 #define COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_ 6 #define COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_
7 7
8 #include <memory> 8 #include <memory>
9 #include <string> 9 #include <string>
10 10
11 #include "base/callback.h"
11 #include "base/command_line.h" 12 #include "base/command_line.h"
12 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
13 #include "base/gtest_prod_util.h" 14 #include "base/gtest_prod_util.h"
14 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/weak_ptr.h"
15 #include "base/threading/thread_checker.h" 18 #include "base/threading/thread_checker.h"
19 #include "net/log/net_log_capture_mode.h"
16 20
17 namespace base { 21 namespace base {
18 class DictionaryValue; 22 class DictionaryValue;
23 class SingleThreadTaskRunner;
24 class Value;
19 } 25 }
20 26
21 namespace net { 27 namespace net {
22 class NetLogCaptureMode; 28 class FileNetLogObserver;
23 class WriteToFileNetLogObserver; 29 class URLRequestContextGetter;
24 } 30 }
25 31
26 namespace net_log { 32 namespace net_log {
27 33
28 class ChromeNetLog; 34 class ChromeNetLog;
29 35
30 // NetLogFileWriter logs all the NetLog entries into a specified file. 36 // NetLogFileWriter logs all the NetLog entries into a specified file. It does
eroman 2017/01/11 19:18:38 I suggest also mentioning that this is used exclus
wangyix1 2017/01/14 02:15:47 Done.
37 // so by managing an instance of net::FileNetLogObserver and handles the
38 // attaching/detaching of it to the ChromeNetLog.
31 // 39 //
32 // NetLogFileWriter maintains the current logging state (state_) and log file 40 // NetLogFileWriter maintains the current logging state (using the members
33 // type (log_type_) of the logging into a chrome-net-export-log.json file. 41 // (|state_|, |log_exists_|, |log_capture_mode_known_|, |log_capture_mode_|).
42 // Its three main commands are StartNetLog(), StopNetLog() and GetState(). These
43 // are the only functions that may cause NetLogFileWriter to change state.
44 // Also, NetLogFileWriter is lazily initialized. A portion of the initialization
45 // needs to run on the |file_task_runner_|.
34 // 46 //
35 // The following are the possible states 47 // This class is created and destroyed on the UI thread, and all public entry
36 // a) Only Start is allowed (STATE_NOT_LOGGING, LOG_TYPE_NONE). 48 // points are to be called on the UI thread. Internally, the class may run some
37 // b) Only Stop is allowed (STATE_LOGGING). 49 // code on the |file_task_runner_| and |net_task_runner_|.
38 // c) Either Send or Start is allowed (STATE_NOT_LOGGING, anything but
39 // LOG_TYPE_NONE).
40 //
41 // This is created/destroyed on the main thread, but all other function calls
42 // occur on a background thread.
43 //
44 // This relies on the UI thread outlasting all other threads for thread safety.
45 class NetLogFileWriter { 50 class NetLogFileWriter {
46 public: 51 public:
47 // This enum lists the UI button commands it could receive. 52 ~NetLogFileWriter();
48 enum Command {
49 DO_START_LOG_BYTES, // Call StartNetLog logging all bytes received.
50 DO_START, // Call StartNetLog.
51 DO_START_STRIP_PRIVATE_DATA, // Call StartNetLog stripping private data.
52 DO_STOP, // Call StopNetLog.
53 };
54 53
55 virtual ~NetLogFileWriter(); 54 // The three main commands StartNetLog(), StopNetLog(), and GetState() all
55 // accept a |state_callback| param which can be used to notify the caller of
56 // NetLogFileWriter's new state after a command finshes. |state_callback| will
57 // always be executed by a command even if the command ends up being a no-op
58 // or if some failure occurs.
59 using StateCallback =
60 base::Callback<void(std::unique_ptr<base::DictionaryValue>)>;
56 61
57 // Accepts the button command and executes it. 62 // Starts collecting NetLog data into the file at |log_path|. If |log_path| is
58 void ProcessCommand(Command command); 63 // empty, the default log path is used. It is a no-op if we are
64 // already collecting data into a file, and |capture_mode| is ignored.
65 // ignored.
66 // TODO(mmenke): That's rather weird behavior, think about improving it.
67 //
68 // If NetLogFileWriter is not initialized, this will trigger initialization
69 // and |state_callback| will be executed at the end of StartNetLog()
70 // asynchronously (whether initialization is successful or not). Otherwise,
71 // |state_callback| will be executed at the end synchronously.
eroman 2017/01/11 19:18:39 Instead of having a synchronous case, can you make
wangyix1 2017/01/14 02:15:47 Done.
72 void StartNetLog(const base::FilePath& log_path,
73 net::NetLogCaptureMode capture_mode,
74 const StateCallback& state_callback);
59 75
60 // Returns true and the path to the file. If there is no file to 76 // Stops collecting NetLog data into the file. It is a no-op if we
eroman 2017/01/11 19:18:39 nit: can you modify the language to avoid "we" ?
wangyix1 2017/01/14 02:15:47 Done.
61 // send, then it returns false. It also returns false when actively logging to 77 // are not currently logging.
62 // the file. 78 //
63 bool GetFilePath(base::FilePath* path); 79 // |polled_data| is a JSON dictionary that will be appended to the end of the
80 // log; it's for adding additional info to the log that aren't events.
81 // StopNetLog() will automatically append net info (from net::GetNetInfo())
82 // to |polled_data|, which it will retrieve using |context_getter|.
83 //
84 // |state_callback| will always be executed at the end of StopNetLog()
85 // (even if this function does a no-op or if some failure occurs). It will
86 // be executed asynchronously.
87 void StopNetLog(std::unique_ptr<base::DictionaryValue> polled_data,
88 scoped_refptr<net::URLRequestContextGetter> context_getter,
89 const StateCallback& state_callback);
64 90
65 // Creates a Value summary of the state of the NetLogFileWriter. The caller is 91 // Creates a Value summary of the state of the NetLogFileWriter and calls
66 // responsible for deleting the returned value. 92 // |state_callback| with that Value as the param.
67 base::DictionaryValue* GetState(); 93 //
94 // If NetLogFileWriter is not initialized, this will trigger initialization
95 // and |state_callback| will be executed at the end of GetState()
96 // asynchronously (whether initialization is successful or not). Otherwise,
eroman 2017/01/11 19:18:39 Same comment as earlier -- it is easier for consum
wangyix1 2017/01/14 02:15:47 Done.
97 // |state_callback| will be executed at the end synchronously.
98 void GetState(const StateCallback& state_callback);
68 99
69 // Updates |log_path_| to the |custom_path|. 100 using FilePathCallback = base::Callback<void(const base::FilePath&)>;
eroman 2017/01/11 19:18:39 nit: move this to the top of the class declaration
wangyix1 2017/01/14 02:15:47 Done.
70 void SetUpNetExportLogPath(const base::FilePath& custom_path); 101
102 // Gets the log filepath. |path_callback| will be used to notify the caller
eroman 2017/01/11 19:18:39 Excellent comments!
wangyix1 2017/01/14 02:15:47 Acknowledged.
103 // when the filepath is retrieved. |path_callback| will be executed with an
104 // empty filepath if any of the following occurs:
105 // (1) The log file does not exist.
106 // (2) The NetLogFileWriter is currently logging.
107 // (3) The log file's permissions could not be set to all.
108 //
109 // In cases (1) and (2), |path_callback| will be executed synchronously. In
eroman 2017/01/11 19:18:39 Same comment -- can we make all the completions as
wangyix1 2017/01/14 02:15:47 Done.
110 // case (3) and the success case, it will be executed asynchronously.
111 void GetFilePath(const FilePathCallback& path_callback) const;
eroman 2017/01/11 19:18:39 [optional] I suggest changing this function's name
wangyix1 2017/01/14 02:15:47 Done.
112
113 // Sets the task runners used by NetLogFileWriter for running file-specific
eroman 2017/01/11 19:18:38 I suggest expanding this comment: Sets the task r
wangyix1 2017/01/14 02:15:47 Done.
114 // and net-specific tasks that must be run on those threads.
115 void SetTaskRunners(
116 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner,
117 scoped_refptr<base::SingleThreadTaskRunner> net_task_runner);
118
119 static std::string CaptureModeToString(net::NetLogCaptureMode capture_mode);
eroman 2017/01/11 19:18:38 Suggest adding this comment: // Converts to/from
wangyix1 2017/01/14 02:15:47 Done.
120 static net::NetLogCaptureMode CaptureModeFromString(
121 const std::string& capture_mode_string);
71 122
72 protected: 123 protected:
73 // Constructs a NetLogFileWriter. Only one instance is created in browser 124 // Constructs a NetLogFileWriter. Only one instance is created in browser
74 // process. 125 // process.
75 NetLogFileWriter(ChromeNetLog* chrome_net_log, 126 NetLogFileWriter(ChromeNetLog* chrome_net_log,
76 const base::CommandLine::StringType& command_line_string, 127 const base::CommandLine::StringType& command_line_string,
77 const std::string& channel_string); 128 const std::string& channel_string);
78 129
79 // Returns path name to base::GetTempDir() directory. Returns false if
80 // base::GetTempDir() fails.
81 virtual bool GetNetExportLogBaseDirectory(base::FilePath* path) const;
82
83 private: 130 private:
84 friend class ChromeNetLog; 131 friend class ChromeNetLog;
85 friend class NetLogFileWriterTest; 132 friend class NetLogFileWriterTest;
86 133
87 // Allow tests to access our innards for testing purposes. 134 // Allow tests to access our innards for testing purposes.
88 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitFailure); 135 /*FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitFailure);
eroman 2017/01/11 19:18:39 NOTE: I assume this will be updated in a subsequen
wangyix1 2017/01/14 02:15:47 Acknowledged.
89 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStart); 136 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStart);
90 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStartOrSend); 137 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, EnsureInitAllowStartOrSend);
91 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, ProcessCommandDoStartAndStop); 138 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, ProcessCommandDoStartAndStop);
92 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, DoStartClearsFile); 139 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, DoStartClearsFile);
93 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEvent); 140 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEvent);
94 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEventWithCustomPath); 141 FRIEND_TEST_ALL_PREFIXES(NetLogFileWriterTest, CheckAddEventWithCustomPath);
142 */
95 143
96 // This enum lists the possible state NetLogFileWriter could be in. It is used 144 // The possible logging states of NetLogFileWriter.
97 // to enable/disable "Start", "Stop" and "Send" (email) UI actions.
98 enum State { 145 enum State {
99 STATE_UNINITIALIZED, 146 STATE_UNINITIALIZED,
147 // Currently in the process of initializing.
148 STATE_INITIALIZING,
100 // Not currently logging to file. 149 // Not currently logging to file.
101 STATE_NOT_LOGGING, 150 STATE_NOT_LOGGING,
102 // Currently logging to file. 151 // Currently logging to file.
103 STATE_LOGGING, 152 STATE_LOGGING,
153 // Currently in the process of stopping the log.
154 STATE_STOPPING_LOG,
104 }; 155 };
105 156
106 // The type of the current log file on disk. 157 // Helper function used by commands that may trigger initialization
107 enum LogType { 158 // (StartNetLog(), GetState()). This function attemps to initialize
eroman 2017/01/11 19:18:39 typo: attempts
wangyix1 2017/01/14 02:15:47 Done.
108 // There is no current log file. 159 // NetLogFileWriter asynchronously, then executes |callback|.
109 LOG_TYPE_NONE, 160 void InitAndCallback(const base::Closure& callback);
eroman 2017/01/11 19:18:39 [optional] InitThenCallback() ?
wangyix1 2017/01/14 02:15:47 Done.
110 // The file predates this session. May or may not have private data. 161
111 // TODO(davidben): This state is kind of silly. 162 // Struct used to store the results of SetUpDefaultLogPath() which will be
112 LOG_TYPE_UNKNOWN, 163 // passed to InitStateAndCallback().
113 // The log includes raw bytes. 164 struct DefaultLogPathResults {
eroman 2017/01/11 19:18:39 Move the struct declaration to be below the enum S
wangyix1 2017/01/14 02:15:47 Done.
114 LOG_TYPE_LOG_BYTES, 165 bool default_log_path_success;
115 // The file includes all data. 166 base::FilePath default_log_path;
116 LOG_TYPE_NORMAL, 167 bool log_exists;
117 // The file has credentials and cookies stripped.
118 LOG_TYPE_STRIP_PRIVATE_DATA,
119 }; 168 };
120 169
121 // Returns the NetLog::CaptureMode corresponding to a LogType. 170 // Contains file-related initialization tasks. Will run on the file task
122 static net::NetLogCaptureMode GetCaptureModeForLogType(LogType log_type); 171 // runner.
172 static DefaultLogPathResults SetUpDefaultLogPath();
123 173
124 // Initializes the |state_| to STATE_NOT_LOGGING and |log_type_| to 174 // Initializes |state_| and |log_path_| using results from
125 // LOG_TYPE_NONE (if there is no file from earlier run) or 175 // SetUpDefaultLogPath(), then executes |callback|.
eroman 2017/01/11 19:18:39 mention if the execution of |callback| is synchro
wangyix1 2017/01/14 02:15:47 Done.
126 // LOG_TYPE_UNKNOWN (if there is a file from earlier run). Returns 176 void InitStateAndCallback(const base::Closure& callback,
127 // false if initialization of |log_path_| fails. 177 const DefaultLogPathResults& results);
128 bool EnsureInit();
129 178
130 // Start collecting NetLog data into chrome-net-export-log.json file in 179 void StartLogging(const base::FilePath& log_path,
131 // a directory, using the specified capture mode. It is a no-op if we are 180 net::NetLogCaptureMode capture_mode,
132 // already collecting data into a file, and |capture_mode| is ignored. 181 const StateCallback& state_callback);
133 // ignored.
134 // TODO(mmenke): That's rather weird behavior, think about improving it.
135 void StartNetLog(LogType log_type);
136 182
137 // Stop collecting NetLog data into the file. It is a no-op if we 183 // Adds net info from net::GetNetInfo() to |polled_data|. Will run on the
eroman 2017/01/11 19:18:39 Will run on the --> must be run on the
wangyix1 2017/01/14 02:15:47 Done.
138 // are not collecting data into a file. 184 // net task runner.
139 void StopNetLog(); 185 static std::unique_ptr<base::DictionaryValue> AddNetInfo(
eroman 2017/01/11 19:18:39 Consider moving this declaration to the .cc (i.e.
wangyix1 2017/01/14 02:15:47 Done.
186 scoped_refptr<net::URLRequestContextGetter> context_getter,
187 std::unique_ptr<base::DictionaryValue> polled_data);
140 188
141 // Updates |log_path_| to be the base::FilePath to use for log files, which 189 void StopLogging(const StateCallback& state_callback,
142 // will be inside the base::GetTempDir() directory. Returns false if 190 std::unique_ptr<base::DictionaryValue> polled_data);
143 // base::GetTempDir() fails, or unable to create a subdirectory for logging
144 // within that directory.
145 bool SetUpDefaultNetExportLogPath();
146 191
147 // Returns true if a file exists at |log_path_|. 192 void ResetObserverThenSetStateNotLogging(const StateCallback& state_callback);
148 bool NetExportLogExists() const; 193
194 std::unique_ptr<base::DictionaryValue> GetState() const;
195
196 // Gets the state and runs |state_callback|.
197 void RunStateCallback(const StateCallback& state_callback) const;
198
199 // If running on a POSIX OS, this sets all the permission flags of the file at
200 // |path| to 1. Returns false if file does not exist.
201 static bool SetPosixFilePermissionsAll(const base::FilePath& path);
eroman 2017/01/11 19:18:38 This can also be moved to the .cc file (i.e. remo
wangyix1 2017/01/14 02:15:47 Done.
202
203 // If |set_file_permissions_success| is true, |path_callback| is executed with
204 // |path|. Otherwise, |path_callback| is executed with empty path.
205 static void RunFilePathCallback(const FilePathCallback& path_callback,
206 const base::FilePath& path,
207 bool set_file_permissions_success);
208
209 // Helper function for unit tests.
210 State state() const { return state_; }
211
212 // All members are accessed solely from the main thread (the thread that
213 // |thread_checker_| is bound to).
149 214
150 base::ThreadChecker thread_checker_; 215 base::ThreadChecker thread_checker_;
151 216
152 // Helper function for unit tests. 217 // Task runners for file-specific and net-specific tasks that must run on a
153 State state() const { return state_; } 218 // file or net thread.
154 LogType log_type() const { return log_type_; } 219 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
220 scoped_refptr<base::SingleThreadTaskRunner> net_task_runner_;
155 221
156 State state_; // Current state of NetLogFileWriter. 222 State state_; // Current logging state of NetLogFileWriter.
157 LogType log_type_; // Type of current log file on disk. 223
224 bool log_exists_; // Whether or not the log exists on disk.
225 bool log_capture_mode_known_;
226 net::NetLogCaptureMode log_capture_mode_;
158 227
159 base::FilePath log_path_; // base::FilePath to the NetLog file. 228 base::FilePath log_path_; // base::FilePath to the NetLog file.
160 229
161 // |write_to_file_observer_| watches the NetLog event stream, and 230 // |write_to_file_observer_| watches the NetLog event stream, and
162 // sends all entries to the file created in StartNetLog(). 231 // sends all entries to the file created in StartNetLog().
163 std::unique_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; 232 std::unique_ptr<net::FileNetLogObserver> write_to_file_observer_;
164 233
165 // The |chrome_net_log_| is owned by the browser process, cached here to avoid 234 // The |chrome_net_log_| is owned by the browser process, cached here to avoid
166 // using global (g_browser_process). 235 // using global (g_browser_process).
167 ChromeNetLog* chrome_net_log_; 236 ChromeNetLog* chrome_net_log_;
168 237
169 const base::CommandLine::StringType command_line_string_; 238 const base::CommandLine::StringType command_line_string_;
170 const std::string channel_string_; 239 const std::string channel_string_;
171 240
241 base::WeakPtrFactory<NetLogFileWriter> weak_ptr_factory_;
242
172 DISALLOW_COPY_AND_ASSIGN(NetLogFileWriter); 243 DISALLOW_COPY_AND_ASSIGN(NetLogFileWriter);
173 }; 244 };
174 245
175 } // namespace net_log 246 } // namespace net_log
176 247
177 #endif // COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_ 248 #endif // COMPONENTS_NET_LOG_NET_LOG_FILE_WRITER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698