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
CreateLogParser(const std::string & log_type)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
CollectLogInfo(FilterHandler * filter_handler,system_logs::SystemLogsResponse * logs,std::vector<linked_ptr<api::log_private::LogEntry>> * output)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
Get(content::BrowserContext * context)67 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) {
68 return GetFactoryInstance()->Get(context);
69 }
70
LogPrivateAPI(content::BrowserContext * context)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
~LogPrivateAPI()78 LogPrivateAPI::~LogPrivateAPI() {
79 }
80
StartNetInternalsWatch(const std::string & extension_id)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
StopNetInternalsWatch(const std::string & extension_id)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>*
GetFactoryInstance()99 LogPrivateAPI::GetFactoryInstance() {
100 return g_factory.Pointer();
101 }
102
OnAddEntry(const net::NetLog::Entry & entry)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
PostPendingEntries()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
AddEntriesOnUI(scoped_ptr<base::ListValue> value)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
MaybeStartNetInternalLogging()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
MaybeStopNetInternalLogging()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
StopNetInternalLogging()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
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionInfo::Reason reason)164 void LogPrivateAPI::OnExtensionUnloaded(
165 content::BrowserContext* browser_context,
166 const Extension* extension,
167 UnloadedExtensionInfo::Reason reason) {
168 StopNetInternalsWatch(extension->id());
169 }
170
LogPrivateGetHistoricalFunction()171 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() {
172 }
173
~LogPrivateGetHistoricalFunction()174 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() {
175 }
176
RunAsync()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
OnSystemLogsLoaded(scoped_ptr<system_logs::SystemLogsResponse> sys_info)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::
LogPrivateStartNetInternalsWatchFunction()212 LogPrivateStartNetInternalsWatchFunction() {
213 }
214
215 LogPrivateStartNetInternalsWatchFunction::
~LogPrivateStartNetInternalsWatchFunction()216 ~LogPrivateStartNetInternalsWatchFunction() {
217 }
218
RunSync()219 bool LogPrivateStartNetInternalsWatchFunction::RunSync() {
220 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch(extension_id());
221 return true;
222 }
223
224 LogPrivateStopNetInternalsWatchFunction::
LogPrivateStopNetInternalsWatchFunction()225 LogPrivateStopNetInternalsWatchFunction() {
226 }
227
228 LogPrivateStopNetInternalsWatchFunction::
~LogPrivateStopNetInternalsWatchFunction()229 ~LogPrivateStopNetInternalsWatchFunction() {
230 }
231
RunSync()232 bool LogPrivateStopNetInternalsWatchFunction::RunSync() {
233 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id());
234 return true;
235 }
236
237 } // namespace extensions
238