• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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