Home | History | Annotate | Download | only in log_private
      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