OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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 #include "chrome/browser/extensions/api/log_private/log_private_api.h" | 5 #include "chrome/browser/extensions/api/log_private/log_private_api.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | |
10 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" |
11 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/memory/linked_ptr.h" | 14 #include "base/memory/linked_ptr.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
15 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/download/download_prefs.h" | |
18 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" | |
16 #include "chrome/browser/extensions/api/log_private/filter_handler.h" | 19 #include "chrome/browser/extensions/api/log_private/filter_handler.h" |
17 #include "chrome/browser/extensions/api/log_private/log_parser.h" | 20 #include "chrome/browser/extensions/api/log_private/log_parser.h" |
18 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" | 21 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" |
19 #include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h" | 22 #include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h" |
20 #include "chrome/browser/io_thread.h" | 23 #include "chrome/browser/io_thread.h" |
21 #include "chrome/browser/net/chrome_net_log.h" | 24 #include "chrome/browser/net/chrome_net_log.h" |
22 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
23 #include "chrome/common/extensions/api/log_private.h" | 26 #include "chrome/common/extensions/api/log_private.h" |
27 #include "chrome/common/logging_chrome.h" | |
28 #include "content/public/browser/render_process_host.h" | |
24 #include "extensions/browser/event_router.h" | 29 #include "extensions/browser/event_router.h" |
25 #include "extensions/browser/extension_function.h" | 30 #include "extensions/browser/extension_function.h" |
26 #include "extensions/browser/extension_registry.h" | 31 #include "extensions/browser/extension_registry.h" |
32 #include "extensions/browser/granted_file_entry.h" | |
33 | |
34 #if defined(OS_CHROMEOS) | |
35 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h" | |
36 #endif | |
27 | 37 |
28 using content::BrowserThread; | 38 using content::BrowserThread; |
29 | 39 |
30 namespace events { | 40 namespace events { |
31 const char kOnAddNetInternalsEntries[] = "logPrivate.onAddNetInternalsEntries"; | 41 const char kOnAddNetInternalsEntries[] = "logPrivate.onAddNetInternalsEntries"; |
32 } // namespace events | 42 } // namespace events |
33 | 43 |
34 namespace extensions { | 44 namespace extensions { |
35 namespace { | 45 namespace { |
36 | 46 |
47 const char kLogFileNameBase[] = "net-internals"; | |
37 const int kNetLogEventDelayMilliseconds = 100; | 48 const int kNetLogEventDelayMilliseconds = 100; |
38 | 49 |
39 scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { | 50 scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { |
40 if (log_type == "syslog") | 51 if (log_type == "syslog") |
41 return scoped_ptr<LogParser>(new SyslogParser()); | 52 return scoped_ptr<LogParser>(new SyslogParser()); |
42 // TODO(shinfan): Add more parser here | 53 // TODO(shinfan): Add more parser here |
43 | 54 |
44 NOTREACHED() << "Invalid log type: " << log_type; | 55 NOTREACHED() << "Invalid log type: " << log_type; |
45 return scoped_ptr<LogParser>(); | 56 return scoped_ptr<LogParser>(); |
46 } | 57 } |
(...skipping 17 matching lines...) Expand all Loading... | |
64 } // namespace | 75 } // namespace |
65 | 76 |
66 // static | 77 // static |
67 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { | 78 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { |
68 return GetFactoryInstance()->Get(context); | 79 return GetFactoryInstance()->Get(context); |
69 } | 80 } |
70 | 81 |
71 LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) | 82 LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) |
72 : browser_context_(context), | 83 : browser_context_(context), |
73 logging_net_internals_(false), | 84 logging_net_internals_(false), |
85 event_sink_(LogPrivateAPI::REPORT_EVENTS_TO_EXTENSION), | |
74 extension_registry_observer_(this) { | 86 extension_registry_observer_(this) { |
75 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 87 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
76 } | 88 } |
77 | 89 |
78 LogPrivateAPI::~LogPrivateAPI() { | 90 LogPrivateAPI::~LogPrivateAPI() { |
79 } | 91 } |
80 | 92 |
81 void LogPrivateAPI::StartNetInternalsWatch(const std::string& extension_id) { | 93 void LogPrivateAPI::StartNetInternalsWatch( |
94 const std::string& extension_id, | |
95 LogPrivateAPI::CapturedEventsSink event_sink) { | |
82 net_internal_watches_.insert(extension_id); | 96 net_internal_watches_.insert(extension_id); |
83 BrowserThread::PostTask( | 97 BrowserThread::PostTask( |
84 BrowserThread::IO, FROM_HERE, | 98 BrowserThread::IO, FROM_HERE, |
85 base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, | 99 base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, |
86 base::Unretained(this))); | 100 base::Unretained(this), |
101 event_sink)); | |
87 } | 102 } |
88 | 103 |
89 void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id) { | 104 void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id, |
105 const base::Closure& closure) { | |
90 net_internal_watches_.erase(extension_id); | 106 net_internal_watches_.erase(extension_id); |
91 MaybeStopNetInternalLogging(); | 107 MaybeStopNetInternalLogging(closure); |
108 } | |
109 | |
110 void LogPrivateAPI::StopAllWatches(const std::string& extension_id, | |
111 const base::Closure& closure) { | |
112 StopNetInternalsWatch(extension_id, closure); | |
92 } | 113 } |
93 | 114 |
94 static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > | 115 static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > |
95 g_factory = LAZY_INSTANCE_INITIALIZER; | 116 g_factory = LAZY_INSTANCE_INITIALIZER; |
96 | 117 |
97 // static | 118 // static |
98 BrowserContextKeyedAPIFactory<LogPrivateAPI>* | 119 BrowserContextKeyedAPIFactory<LogPrivateAPI>* |
99 LogPrivateAPI::GetFactoryInstance() { | 120 LogPrivateAPI::GetFactoryInstance() { |
100 return g_factory.Pointer(); | 121 return g_factory.Pointer(); |
101 } | 122 } |
(...skipping 26 matching lines...) Expand all Loading... | |
128 // Create the event's arguments value. | 149 // Create the event's arguments value. |
129 scoped_ptr<base::ListValue> event_args(new base::ListValue()); | 150 scoped_ptr<base::ListValue> event_args(new base::ListValue()); |
130 event_args->Append(value->DeepCopy()); | 151 event_args->Append(value->DeepCopy()); |
131 scoped_ptr<Event> event(new Event(events::kOnAddNetInternalsEntries, | 152 scoped_ptr<Event> event(new Event(events::kOnAddNetInternalsEntries, |
132 event_args.Pass())); | 153 event_args.Pass())); |
133 EventRouter::Get(browser_context_) | 154 EventRouter::Get(browser_context_) |
134 ->DispatchEventToExtension(*ix, event.Pass()); | 155 ->DispatchEventToExtension(*ix, event.Pass()); |
135 } | 156 } |
136 } | 157 } |
137 | 158 |
138 void LogPrivateAPI::MaybeStartNetInternalLogging() { | 159 void LogPrivateAPI::MaybeStartNetInternalLogging( |
160 LogPrivateAPI::CapturedEventsSink event_sink) { | |
139 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 161 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
140 if (!logging_net_internals_) { | 162 if (!logging_net_internals_) { |
141 g_browser_process->io_thread()->net_log()->AddThreadSafeObserver( | |
142 this, net::NetLog::LOG_ALL_BUT_BYTES); | |
143 logging_net_internals_ = true; | 163 logging_net_internals_ = true; |
164 event_sink_ = event_sink; | |
165 switch (event_sink_) { | |
166 case REPORT_EVENTS_TO_EXTENSION: { | |
167 g_browser_process->io_thread()->net_log()->AddThreadSafeObserver( | |
168 this, net::NetLog::LOG_ALL_BUT_BYTES); | |
169 break; | |
170 } | |
171 case RECORD_EVENTS_TO_FILE: { | |
172 base::FilePath file_path = | |
173 logging::GetSessionLogDir( | |
174 *CommandLine::ForCurrentProcess()).Append(kLogFileNameBase); | |
175 file_path = logging::GenerateTimestampedName(file_path, | |
176 base::Time::Now()); | |
177 FILE* file = NULL; | |
178 file = fopen(file_path.value().c_str(), "w"); | |
179 if (file == NULL) { | |
180 LOG(ERROR) << "Could not open file " << file_path.value() | |
181 << " for net logging"; | |
182 } else { | |
183 scoped_ptr<base::Value> constants(net::NetLogLogger::GetConstants()); | |
184 net_log_logger_.reset(new net::NetLogLogger(file, *constants)); | |
185 net_log_logger_->set_log_level(net::NetLog::LOG_ALL_BUT_BYTES); | |
186 net_log_logger_->StartObserving( | |
187 g_browser_process->io_thread()->net_log()); | |
188 } | |
189 break; | |
190 } | |
191 } | |
144 } | 192 } |
145 } | 193 } |
146 | 194 |
147 void LogPrivateAPI::MaybeStopNetInternalLogging() { | 195 void LogPrivateAPI::MaybeStopNetInternalLogging(const base::Closure& closure) { |
148 if (net_internal_watches_.empty()) { | 196 if (net_internal_watches_.empty()) { |
149 BrowserThread::PostTask( | 197 BrowserThread::PostTaskAndReply( |
150 BrowserThread::IO, FROM_HERE, | 198 BrowserThread::IO, FROM_HERE, |
151 base::Bind(&LogPrivateAPI:: StopNetInternalLogging, | 199 base::Bind(&LogPrivateAPI:: StopNetInternalLogging, |
152 base::Unretained(this))); | 200 base::Unretained(this)), |
201 closure); | |
153 } | 202 } |
154 } | 203 } |
155 | 204 |
156 void LogPrivateAPI::StopNetInternalLogging() { | 205 void LogPrivateAPI::StopNetInternalLogging() { |
157 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 206 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
158 if (net_log() && logging_net_internals_) { | 207 if (net_log() && logging_net_internals_) { |
159 net_log()->RemoveThreadSafeObserver(this); | |
160 logging_net_internals_ = false; | 208 logging_net_internals_ = false; |
209 switch (event_sink_) { | |
210 case REPORT_EVENTS_TO_EXTENSION: | |
211 net_log()->RemoveThreadSafeObserver(this); | |
212 break; | |
213 case RECORD_EVENTS_TO_FILE: | |
214 net_log_logger_->StopObserving(); | |
215 net_log_logger_.reset(); | |
216 break; | |
217 } | |
161 } | 218 } |
162 } | 219 } |
163 | 220 |
164 void LogPrivateAPI::OnExtensionUnloaded( | 221 void LogPrivateAPI::OnExtensionUnloaded( |
165 content::BrowserContext* browser_context, | 222 content::BrowserContext* browser_context, |
166 const Extension* extension, | 223 const Extension* extension, |
167 UnloadedExtensionInfo::Reason reason) { | 224 UnloadedExtensionInfo::Reason reason) { |
168 StopNetInternalsWatch(extension->id()); | 225 StopNetInternalsWatch(extension->id(), base::Closure()); |
169 } | 226 } |
170 | 227 |
171 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { | 228 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { |
172 } | 229 } |
173 | 230 |
174 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() { | 231 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() { |
175 } | 232 } |
176 | 233 |
177 bool LogPrivateGetHistoricalFunction::RunAsync() { | 234 bool LogPrivateGetHistoricalFunction::RunAsync() { |
178 // Get parameters | 235 // Get parameters |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 | 267 |
211 LogPrivateStartNetInternalsWatchFunction:: | 268 LogPrivateStartNetInternalsWatchFunction:: |
212 LogPrivateStartNetInternalsWatchFunction() { | 269 LogPrivateStartNetInternalsWatchFunction() { |
213 } | 270 } |
214 | 271 |
215 LogPrivateStartNetInternalsWatchFunction:: | 272 LogPrivateStartNetInternalsWatchFunction:: |
216 ~LogPrivateStartNetInternalsWatchFunction() { | 273 ~LogPrivateStartNetInternalsWatchFunction() { |
217 } | 274 } |
218 | 275 |
219 bool LogPrivateStartNetInternalsWatchFunction::RunSync() { | 276 bool LogPrivateStartNetInternalsWatchFunction::RunSync() { |
220 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch(extension_id()); | 277 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch( |
278 extension_id(), | |
279 LogPrivateAPI::REPORT_EVENTS_TO_EXTENSION); | |
221 return true; | 280 return true; |
222 } | 281 } |
223 | 282 |
224 LogPrivateStopNetInternalsWatchFunction:: | 283 LogPrivateStopNetInternalsWatchFunction:: |
225 LogPrivateStopNetInternalsWatchFunction() { | 284 LogPrivateStopNetInternalsWatchFunction() { |
226 } | 285 } |
227 | 286 |
228 LogPrivateStopNetInternalsWatchFunction:: | 287 LogPrivateStopNetInternalsWatchFunction:: |
229 ~LogPrivateStopNetInternalsWatchFunction() { | 288 ~LogPrivateStopNetInternalsWatchFunction() { |
230 } | 289 } |
231 | 290 |
232 bool LogPrivateStopNetInternalsWatchFunction::RunSync() { | 291 bool LogPrivateStopNetInternalsWatchFunction::RunSync() { |
233 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id()); | 292 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id(), |
293 base::Closure()); | |
234 return true; | 294 return true; |
235 } | 295 } |
236 | 296 |
297 LogPrivateStartEventRecorderFunction::LogPrivateStartEventRecorderFunction() { | |
298 } | |
299 | |
300 LogPrivateStartEventRecorderFunction::~LogPrivateStartEventRecorderFunction() { | |
301 } | |
302 | |
303 bool LogPrivateStartEventRecorderFunction::RunSync() { | |
304 scoped_ptr<api::log_private::StartEventRecorder::Params> params( | |
305 api::log_private::StartEventRecorder::Params::Create(*args_)); | |
306 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
307 if (params->type == api::log_private::EVENT_TYPE_NETWORK) { | |
Zachary Kuznia
2014/06/27 22:34:07
Nit: switch on type here, too.
zel
2014/07/14 19:14:41
Done.
| |
308 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch( | |
309 extension_id(), | |
310 LogPrivateAPI::RECORD_EVENTS_TO_FILE); | |
311 } else { | |
312 NOTREACHED(); | |
313 return false; | |
314 } | |
315 | |
316 return true; | |
317 } | |
318 | |
319 LogPrivateStopEventRecorderFunction::LogPrivateStopEventRecorderFunction() { | |
320 } | |
321 | |
322 LogPrivateStopEventRecorderFunction::~LogPrivateStopEventRecorderFunction() { | |
323 } | |
324 | |
325 bool LogPrivateStopEventRecorderFunction::RunSync() { | |
326 scoped_ptr<api::log_private::StopEventRecorder::Params> params( | |
327 api::log_private::StopEventRecorder::Params::Create(*args_)); | |
328 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
329 switch (params->type) { | |
330 case api::log_private::EVENT_TYPE_NETWORK: | |
331 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id(), | |
332 base::Closure()); | |
333 break; | |
334 case api::log_private::EVENT_TYPE_NONE: | |
335 NOTREACHED(); | |
336 return false; | |
337 } | |
338 return true; | |
339 } | |
340 | |
341 LogPrivateDumpLogsFunction::LogPrivateDumpLogsFunction() { | |
342 } | |
343 | |
344 LogPrivateDumpLogsFunction::~LogPrivateDumpLogsFunction() { | |
345 } | |
346 | |
347 bool LogPrivateDumpLogsFunction::RunAsync() { | |
348 LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))-> | |
349 StopAllWatches( | |
350 extension_id(), | |
351 base::Bind(&LogPrivateDumpLogsFunction::OnStopAllWatches, this)); | |
352 return true; | |
353 } | |
354 | |
355 void LogPrivateDumpLogsFunction::OnStopAllWatches() { | |
356 const DownloadPrefs* const prefs = | |
357 DownloadPrefs::FromBrowserContext(browser_context()); | |
358 chromeos::DebugLogWriter::StoreLogs( | |
359 prefs->DownloadPath(), | |
360 base::Bind(&LogPrivateDumpLogsFunction::OnStoreLogsCompleted, | |
361 this)); | |
362 } | |
363 | |
364 void LogPrivateDumpLogsFunction::OnStoreLogsCompleted( | |
365 const base::FilePath& log_path, bool succeeded) { | |
366 | |
367 scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); | |
368 extensions::GrantedFileEntry file_entry = | |
369 extensions::app_file_handler_util::CreateFileEntry( | |
370 Profile::FromBrowserContext(browser_context()), | |
371 GetExtension(), | |
372 render_view_host_->GetProcess()->GetID(), | |
373 log_path, | |
374 false); | |
375 | |
376 base::DictionaryValue* entry = new base::DictionaryValue(); | |
377 entry->SetString("fileSystemId", file_entry.filesystem_id); | |
378 entry->SetString("baseName", file_entry.registered_name); | |
379 entry->SetString("id", file_entry.id); | |
380 entry->SetBoolean("isDirectory", false); | |
381 response->Set("entry", entry); | |
382 SetResult(response.release()); | |
383 SendResponse(succeeded); | |
384 } | |
385 | |
386 | |
237 } // namespace extensions | 387 } // namespace extensions |
OLD | NEW |