Chromium Code Reviews| Index: chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc |
| diff --git a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc |
| index 8cce97fff6a3c74d9a1ece04f521826825347e8f..b35b2107388f3ceffc54a301ab7c2ad2c90dd481 100644 |
| --- a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc |
| +++ b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc |
| @@ -7,12 +7,15 @@ |
| #include <string> |
| #include <vector> |
| +#include "base/command_line.h" |
| #include "base/json/json_writer.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/memory/linked_ptr.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/download/download_prefs.h" |
| +#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" |
| #include "chrome/browser/extensions/api/log_private/filter_handler.h" |
| #include "chrome/browser/extensions/api/log_private/log_parser.h" |
| #include "chrome/browser/extensions/api/log_private/syslog_parser.h" |
| @@ -21,9 +24,16 @@ |
| #include "chrome/browser/net/chrome_net_log.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/extensions/api/log_private.h" |
| +#include "chrome/common/logging_chrome.h" |
| +#include "content/public/browser/render_process_host.h" |
| #include "extensions/browser/event_router.h" |
| #include "extensions/browser/extension_function.h" |
| #include "extensions/browser/extension_registry.h" |
| +#include "extensions/browser/granted_file_entry.h" |
| + |
| +#if defined(OS_CHROMEOS) |
| +#include "chrome/browser/chromeos/system_logs/debug_log_writer.h" |
| +#endif |
| using content::BrowserThread; |
| @@ -34,6 +44,7 @@ const char kOnAddNetInternalsEntries[] = "logPrivate.onAddNetInternalsEntries"; |
| namespace extensions { |
| namespace { |
| +const char kLogFileNameBase[] = "net-internals"; |
| const int kNetLogEventDelayMilliseconds = 100; |
| scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { |
| @@ -71,6 +82,7 @@ LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { |
| LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) |
| : browser_context_(context), |
| logging_net_internals_(false), |
| + event_sink_(LogPrivateAPI::REPORT_EVENTS_TO_EXTENSION), |
| extension_registry_observer_(this) { |
| extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
| } |
| @@ -78,17 +90,26 @@ LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) |
| LogPrivateAPI::~LogPrivateAPI() { |
| } |
| -void LogPrivateAPI::StartNetInternalsWatch(const std::string& extension_id) { |
| +void LogPrivateAPI::StartNetInternalsWatch( |
| + const std::string& extension_id, |
| + LogPrivateAPI::CapturedEventsSink event_sink) { |
| net_internal_watches_.insert(extension_id); |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, |
| - base::Unretained(this))); |
| + base::Unretained(this), |
| + event_sink)); |
| } |
| -void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id) { |
| +void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id, |
| + const base::Closure& closure) { |
| net_internal_watches_.erase(extension_id); |
| - MaybeStopNetInternalLogging(); |
| + MaybeStopNetInternalLogging(closure); |
| +} |
| + |
| +void LogPrivateAPI::StopAllWatches(const std::string& extension_id, |
| + const base::Closure& closure) { |
| + StopNetInternalsWatch(extension_id, closure); |
| } |
| static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > |
| @@ -135,29 +156,65 @@ void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) { |
| } |
| } |
| -void LogPrivateAPI::MaybeStartNetInternalLogging() { |
| +void LogPrivateAPI::MaybeStartNetInternalLogging( |
| + LogPrivateAPI::CapturedEventsSink event_sink) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| if (!logging_net_internals_) { |
| - g_browser_process->io_thread()->net_log()->AddThreadSafeObserver( |
| - this, net::NetLog::LOG_ALL_BUT_BYTES); |
| logging_net_internals_ = true; |
| + event_sink_ = event_sink; |
| + switch (event_sink_) { |
| + case REPORT_EVENTS_TO_EXTENSION: { |
| + g_browser_process->io_thread()->net_log()->AddThreadSafeObserver( |
| + this, net::NetLog::LOG_ALL_BUT_BYTES); |
| + break; |
| + } |
| + case RECORD_EVENTS_TO_FILE: { |
| + base::FilePath file_path = |
| + logging::GetSessionLogDir( |
| + *CommandLine::ForCurrentProcess()).Append(kLogFileNameBase); |
| + file_path = logging::GenerateTimestampedName(file_path, |
| + base::Time::Now()); |
| + FILE* file = NULL; |
| + file = fopen(file_path.value().c_str(), "w"); |
| + if (file == NULL) { |
| + LOG(ERROR) << "Could not open file " << file_path.value() |
|
xiaowenx
2014/06/25 05:30:44
Does zork's comment earlier about VLOG(1) also app
zel
2014/06/27 19:31:01
same answer
|
| + << " for net logging"; |
| + } else { |
| + scoped_ptr<base::Value> constants(net::NetLogLogger::GetConstants()); |
| + net_log_logger_.reset(new net::NetLogLogger(file, *constants)); |
| + net_log_logger_->set_log_level(net::NetLog::LOG_ALL_BUT_BYTES); |
| + net_log_logger_->StartObserving( |
| + g_browser_process->io_thread()->net_log()); |
| + } |
| + break; |
| + } |
|
xiaowenx
2014/06/25 05:30:44
Do you want to add in: "default: NOTREACHED()" to
Zachary Kuznia
2014/06/25 18:39:03
Switches with enums generate a compile error if ca
zel
2014/06/27 19:31:01
Yep. We prefer failing in compile time vs. runtime
|
| + } |
| } |
| } |
| -void LogPrivateAPI::MaybeStopNetInternalLogging() { |
| +void LogPrivateAPI::MaybeStopNetInternalLogging(const base::Closure& closure) { |
| if (net_internal_watches_.empty()) { |
| - BrowserThread::PostTask( |
| + BrowserThread::PostTaskAndReply( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&LogPrivateAPI:: StopNetInternalLogging, |
| - base::Unretained(this))); |
| + base::Unretained(this)), |
| + closure); |
| } |
| } |
| void LogPrivateAPI::StopNetInternalLogging() { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| if (net_log() && logging_net_internals_) { |
| - net_log()->RemoveThreadSafeObserver(this); |
| logging_net_internals_ = false; |
| + switch (event_sink_) { |
| + case REPORT_EVENTS_TO_EXTENSION: |
| + net_log()->RemoveThreadSafeObserver(this); |
| + break; |
| + case RECORD_EVENTS_TO_FILE: |
| + net_log_logger_->StopObserving(); |
| + net_log_logger_.reset(); |
| + break; |
|
xiaowenx
2014/06/25 05:30:44
Same as above, do you want to add a default case?
zel
2014/06/27 19:31:01
same as above
|
| + } |
| } |
| } |
| @@ -165,7 +222,7 @@ void LogPrivateAPI::OnExtensionUnloaded( |
| content::BrowserContext* browser_context, |
| const Extension* extension, |
| UnloadedExtensionInfo::Reason reason) { |
| - StopNetInternalsWatch(extension->id()); |
| + StopNetInternalsWatch(extension->id(), base::Closure()); |
| } |
| LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { |
| @@ -217,7 +274,9 @@ LogPrivateStartNetInternalsWatchFunction:: |
| } |
| bool LogPrivateStartNetInternalsWatchFunction::RunSync() { |
| - LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch(extension_id()); |
| + LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch( |
| + extension_id(), |
| + LogPrivateAPI::REPORT_EVENTS_TO_EXTENSION); |
| return true; |
| } |
| @@ -230,8 +289,97 @@ LogPrivateStopNetInternalsWatchFunction:: |
| } |
| bool LogPrivateStopNetInternalsWatchFunction::RunSync() { |
| - LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id()); |
| + LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id(), |
| + base::Closure()); |
| + return true; |
| +} |
| + |
| +LogPrivateStartEventRecorderFunction::LogPrivateStartEventRecorderFunction() { |
| +} |
| + |
| +LogPrivateStartEventRecorderFunction::~LogPrivateStartEventRecorderFunction() { |
| +} |
| + |
| +bool LogPrivateStartEventRecorderFunction::RunSync() { |
| + scoped_ptr<api::log_private::StartEventRecorder::Params> params( |
| + api::log_private::StartEventRecorder::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + if (params->type == api::log_private::EVENT_TYPE_NETWORK) { |
|
Zachary Kuznia
2014/06/25 00:05:53
params->type should be generated as an enum, so if
|
| + LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch( |
| + extension_id(), |
| + LogPrivateAPI::RECORD_EVENTS_TO_FILE); |
|
xiaowenx
2014/06/25 05:30:44
We always want network events to be saved to a fil
zel
2014/06/27 19:31:01
For this API call - yes. Those files are aggregate
|
| + } else { |
| + NOTREACHED(); |
| + return false; |
| + } |
| + |
| return true; |
| } |
| +LogPrivateStopEventRecorderFunction::LogPrivateStopEventRecorderFunction() { |
| +} |
| + |
| +LogPrivateStopEventRecorderFunction::~LogPrivateStopEventRecorderFunction() { |
| +} |
| + |
| +bool LogPrivateStopEventRecorderFunction::RunSync() { |
| + scoped_ptr<api::log_private::StartEventRecorder::Params> params( |
|
xiaowenx
2014/06/25 05:30:44
Should this say "StopEventRecorder::Params" instea
zel
2014/06/27 19:31:01
Good catch. They happen to be the same by accident
|
| + api::log_private::StartEventRecorder::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + if (params->type == api::log_private::EVENT_TYPE_NETWORK) { |
| + LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id(), |
| + base::Closure()); |
| + } else { |
| + NOTREACHED(); |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| +LogPrivateDumpLogsFunction::LogPrivateDumpLogsFunction() { |
| +} |
| + |
| +LogPrivateDumpLogsFunction::~LogPrivateDumpLogsFunction() { |
| +} |
| + |
| +bool LogPrivateDumpLogsFunction::RunAsync() { |
| + LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))-> |
| + StopAllWatches( |
| + extension_id(), |
| + base::Bind(&LogPrivateDumpLogsFunction::OnStopAllWatches, this)); |
| + return true; |
| +} |
| + |
| +void LogPrivateDumpLogsFunction::OnStopAllWatches() { |
| + const DownloadPrefs* const prefs = |
| + DownloadPrefs::FromBrowserContext(browser_context()); |
| + chromeos::DebugLogWriter::StoreLogs( |
| + prefs->DownloadPath(), |
| + base::Bind(&LogPrivateDumpLogsFunction::OnStoreLogsCompleted, |
| + this)); |
| +} |
| + |
| +void LogPrivateDumpLogsFunction::OnStoreLogsCompleted( |
| + const base::FilePath& log_path, bool succeeded) { |
| + |
| + scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); |
| + extensions::GrantedFileEntry file_entry = |
| + extensions::app_file_handler_util::CreateFileEntry( |
| + Profile::FromBrowserContext(browser_context()), |
| + GetExtension(), |
| + render_view_host_->GetProcess()->GetID(), |
| + log_path, |
| + false); |
| + |
| + base::DictionaryValue* entry = new base::DictionaryValue(); |
| + entry->SetString("fileSystemId", file_entry.filesystem_id); |
| + entry->SetString("baseName", file_entry.registered_name); |
| + entry->SetString("id", file_entry.id); |
| + entry->SetBoolean("isDirectory", false); |
| + response->Set("entry", entry); |
| + SetResult(response.release()); |
| + SendResponse(succeeded); |
| +} |
| + |
| + |
| } // namespace extensions |