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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/api/log_private/log_private_api.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/json/json_writer.h" 11 #include "base/lazy_instance.h" 12 #include "base/logging.h" 13 #include "base/memory/linked_ptr.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/extensions/api/log_private/filter_handler.h" 17 #include "chrome/browser/extensions/api/log_private/log_parser.h" 18 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" 19 #include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h" 20 #include "chrome/browser/io_thread.h" 21 #include "chrome/browser/net/chrome_net_log.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/common/extensions/api/log_private.h" 24 #include "extensions/browser/event_router.h" 25 #include "extensions/browser/extension_function.h" 26 #include "extensions/browser/extension_registry.h" 27 28 using content::BrowserThread; 29 30 namespace events { 31 const char kOnAddNetInternalsEntries[] = "logPrivate.onAddNetInternalsEntries"; 32 } // namespace events 33 34 namespace extensions { 35 namespace { 36 37 const int kNetLogEventDelayMilliseconds = 100; 38 39 scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { 40 if (log_type == "syslog") 41 return scoped_ptr<LogParser>(new SyslogParser()); 42 // TODO(shinfan): Add more parser here 43 44 NOTREACHED() << "Invalid log type: " << log_type; 45 return scoped_ptr<LogParser>(); 46 } 47 48 void CollectLogInfo( 49 FilterHandler* filter_handler, 50 system_logs::SystemLogsResponse* logs, 51 std::vector<linked_ptr<api::log_private::LogEntry> >* output) { 52 for (system_logs::SystemLogsResponse::const_iterator 53 request_it = logs->begin(); request_it != logs->end(); ++request_it) { 54 if (!filter_handler->IsValidSource(request_it->first)) { 55 continue; 56 } 57 scoped_ptr<LogParser> parser(CreateLogParser(request_it->first)); 58 if (parser) { 59 parser->Parse(request_it->second, output, filter_handler); 60 } 61 } 62 } 63 64 } // namespace 65 66 // static 67 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { 68 return GetFactoryInstance()->Get(context); 69 } 70 71 LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) 72 : browser_context_(context), 73 logging_net_internals_(false), 74 extension_registry_observer_(this) { 75 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 76 } 77 78 LogPrivateAPI::~LogPrivateAPI() { 79 } 80 81 void LogPrivateAPI::StartNetInternalsWatch(const std::string& extension_id) { 82 net_internal_watches_.insert(extension_id); 83 BrowserThread::PostTask( 84 BrowserThread::IO, FROM_HERE, 85 base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, 86 base::Unretained(this))); 87 } 88 89 void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id) { 90 net_internal_watches_.erase(extension_id); 91 MaybeStopNetInternalLogging(); 92 } 93 94 static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > 95 g_factory = LAZY_INSTANCE_INITIALIZER; 96 97 // static 98 BrowserContextKeyedAPIFactory<LogPrivateAPI>* 99 LogPrivateAPI::GetFactoryInstance() { 100 return g_factory.Pointer(); 101 } 102 103 void LogPrivateAPI::OnAddEntry(const net::NetLog::Entry& entry) { 104 DCHECK_CURRENTLY_ON(BrowserThread::IO); 105 if (!pending_entries_.get()) { 106 pending_entries_.reset(new base::ListValue()); 107 BrowserThread::PostDelayedTask( 108 BrowserThread::IO, FROM_HERE, 109 base::Bind(&LogPrivateAPI::PostPendingEntries, base::Unretained(this)), 110 base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds)); 111 } 112 pending_entries_->Append(entry.ToValue()); 113 } 114 115 void LogPrivateAPI::PostPendingEntries() { 116 BrowserThread::PostTask( 117 BrowserThread::UI, FROM_HERE, 118 base::Bind(&LogPrivateAPI:: AddEntriesOnUI, 119 base::Unretained(this), 120 base::Passed(&pending_entries_))); 121 } 122 123 void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) { 124 DCHECK_CURRENTLY_ON(BrowserThread::UI); 125 126 for (std::set<std::string>::iterator ix = net_internal_watches_.begin(); 127 ix != net_internal_watches_.end(); ++ix) { 128 // Create the event's arguments value. 129 scoped_ptr<base::ListValue> event_args(new base::ListValue()); 130 event_args->Append(value->DeepCopy()); 131 scoped_ptr<Event> event(new Event(events::kOnAddNetInternalsEntries, 132 event_args.Pass())); 133 EventRouter::Get(browser_context_) 134 ->DispatchEventToExtension(*ix, event.Pass()); 135 } 136 } 137 138 void LogPrivateAPI::MaybeStartNetInternalLogging() { 139 DCHECK_CURRENTLY_ON(BrowserThread::IO); 140 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; 144 } 145 } 146 147 void LogPrivateAPI::MaybeStopNetInternalLogging() { 148 if (net_internal_watches_.empty()) { 149 BrowserThread::PostTask( 150 BrowserThread::IO, FROM_HERE, 151 base::Bind(&LogPrivateAPI:: StopNetInternalLogging, 152 base::Unretained(this))); 153 } 154 } 155 156 void LogPrivateAPI::StopNetInternalLogging() { 157 DCHECK_CURRENTLY_ON(BrowserThread::IO); 158 if (net_log() && logging_net_internals_) { 159 net_log()->RemoveThreadSafeObserver(this); 160 logging_net_internals_ = false; 161 } 162 } 163 164 void LogPrivateAPI::OnExtensionUnloaded( 165 content::BrowserContext* browser_context, 166 const Extension* extension, 167 UnloadedExtensionInfo::Reason reason) { 168 StopNetInternalsWatch(extension->id()); 169 } 170 171 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { 172 } 173 174 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() { 175 } 176 177 bool LogPrivateGetHistoricalFunction::RunAsync() { 178 // Get parameters 179 scoped_ptr<api::log_private::GetHistorical::Params> params( 180 api::log_private::GetHistorical::Params::Create(*args_)); 181 EXTENSION_FUNCTION_VALIDATE(params.get()); 182 filter_handler_.reset(new FilterHandler(params->filter)); 183 184 system_logs::SystemLogsFetcherBase* fetcher; 185 if ((params->filter).scrub) { 186 fetcher = new system_logs::ScrubbedSystemLogsFetcher(); 187 } else { 188 fetcher = new system_logs::AboutSystemLogsFetcher(); 189 } 190 fetcher->Fetch( 191 base::Bind(&LogPrivateGetHistoricalFunction::OnSystemLogsLoaded, this)); 192 193 return true; 194 } 195 196 void LogPrivateGetHistoricalFunction::OnSystemLogsLoaded( 197 scoped_ptr<system_logs::SystemLogsResponse> sys_info) { 198 std::vector<linked_ptr<api::log_private::LogEntry> > data; 199 200 CollectLogInfo(filter_handler_.get(), sys_info.get(), &data); 201 202 // Prepare result 203 api::log_private::Result result; 204 result.data = data; 205 api::log_private::Filter::Populate( 206 *((filter_handler_->GetFilter())->ToValue()), &result.filter); 207 SetResult(result.ToValue().release()); 208 SendResponse(true); 209 } 210 211 LogPrivateStartNetInternalsWatchFunction:: 212 LogPrivateStartNetInternalsWatchFunction() { 213 } 214 215 LogPrivateStartNetInternalsWatchFunction:: 216 ~LogPrivateStartNetInternalsWatchFunction() { 217 } 218 219 bool LogPrivateStartNetInternalsWatchFunction::RunSync() { 220 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch(extension_id()); 221 return true; 222 } 223 224 LogPrivateStopNetInternalsWatchFunction:: 225 LogPrivateStopNetInternalsWatchFunction() { 226 } 227 228 LogPrivateStopNetInternalsWatchFunction:: 229 ~LogPrivateStopNetInternalsWatchFunction() { 230 } 231 232 bool LogPrivateStopNetInternalsWatchFunction::RunSync() { 233 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id()); 234 return true; 235 } 236 237 } // namespace extensions 238