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 |