1bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// found in the LICENSE file.
4bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
5bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "chrome/browser/extensions/api/log_private/log_private_api.h"
6bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
7bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include <string>
8bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include <vector>
9bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/command_line.h"
11bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "base/json/json_writer.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/lazy_instance.h"
13bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "base/logging.h"
14bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "base/memory/linked_ptr.h"
15bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "base/memory/scoped_ptr.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/browser_process.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/download/download_prefs.h"
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
19bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "chrome/browser/extensions/api/log_private/filter_handler.h"
20bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "chrome/browser/extensions/api/log_private/log_parser.h"
21bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "chrome/browser/extensions/api/log_private/syslog_parser.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/io_thread.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/net/chrome_net_log.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h"
27bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch#include "chrome/common/extensions/api/log_private.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/common/logging_chrome.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/event_router.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/extension_function.h"
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/browser/extension_registry.h"
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/granted_file_entry.h"
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_CHROMEOS)
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/chromeos/system_logs/debug_log_writer.h"
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread;
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace events {
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kOnCapturedEvents[] = "logPrivate.onCapturedEvents";
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace events
44bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
45bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochnamespace extensions {
46bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochnamespace {
47bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kAppLogsSubdir[] = "apps";
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kLogDumpsSubdir[] = "log_dumps";
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kLogFileNameBase[] = "net-internals";
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kNetLogEventDelayMilliseconds = 100;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Gets sequenced task runner for file specific calls within this API.
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() {
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return pool->GetSequencedTaskRunnerWithShutdownBehavior(
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pool->GetNamedSequenceToken(FileResource::kSequenceToken),
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::SequencedWorkerPool::BLOCK_SHUTDOWN);
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Checks if we are running on sequenced task runner thread.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsRunningOnSequenceThread() {
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool();
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return pool->IsRunningSequenceOnCurrentThread(
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      pool->GetNamedSequenceToken(FileResource::kSequenceToken));
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
68bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochscoped_ptr<LogParser> CreateLogParser(const std::string& log_type) {
69bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  if (log_type == "syslog")
70bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    return scoped_ptr<LogParser>(new SyslogParser());
71bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // TODO(shinfan): Add more parser here
72bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
73bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  NOTREACHED() << "Invalid log type: " << log_type;
74bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return  scoped_ptr<LogParser>();
75bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
76bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
77bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid CollectLogInfo(
78bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    FilterHandler* filter_handler,
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    system_logs::SystemLogsResponse* logs,
80bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    std::vector<linked_ptr<api::log_private::LogEntry> >* output) {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (system_logs::SystemLogsResponse::const_iterator
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request_it = logs->begin(); request_it != logs->end(); ++request_it) {
83bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (!filter_handler->IsValidSource(request_it->first)) {
84bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      continue;
85bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
86bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    scoped_ptr<LogParser> parser(CreateLogParser(request_it->first));
87bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    if (parser) {
88bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      parser->Parse(request_it->second, output, filter_handler);
89bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
90bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  }
91bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
92bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Returns directory location of app-specific logs that are initiated with
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// logPrivate.startEventRecorder() calls - /home/chronos/user/log/apps
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::FilePath GetAppLogDirectory() {
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return logging::GetSessionLogDir(*CommandLine::ForCurrentProcess())
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      .Append(kAppLogsSubdir);
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Returns directory location where logs dumps initiated with chrome.dumpLogs
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// will be stored - /home/chronos/<user_profile_dir>/Downloads/log_dumps
1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)base::FilePath GetLogDumpDirectory(content::BrowserContext* context) {
1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(context);
1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return prefs->DownloadPath().Append(kLogDumpsSubdir);
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Removes direcotry content of |logs_dumps| and |app_logs_dir| (only for the
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// primary profile).
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void CleanUpLeftoverLogs(bool is_primary_profile,
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         const base::FilePath& app_logs_dir,
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         const base::FilePath& logs_dumps) {
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(WARNING) << "Deleting " << app_logs_dir.value();
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LOG(WARNING) << "Deleting " << logs_dumps.value();
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(IsRunningOnSequenceThread());
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::DeleteFile(logs_dumps, true);
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // App-specific logs are stored in /home/chronos/user/log/apps directory that
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // is shared between all profiles in multi-profile case. We should not
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // nuke it for non-primary profiles.
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!is_primary_profile)
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::DeleteFile(app_logs_dir, true);
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
127bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace
128bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char FileResource::kSequenceToken[] = "log_api_files";
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileResource::FileResource(const std::string& owner_extension_id,
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                           const base::FilePath& path)
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : ApiResource(owner_extension_id), path_(path) {
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)FileResource::~FileResource() {
1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::DeleteFile(path_, true);
1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool FileResource::IsPersistent() const {
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return false;
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) {
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LogPrivateAPI* api = GetFactoryInstance()->Get(context);
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  api->Initialize();
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return api;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context)
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    : browser_context_(context),
1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      logging_net_internals_(false),
1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      event_sink_(api::log_private::EVENT_SINK_CAPTURE),
1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extension_registry_observer_(this),
1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      log_file_resources_(context),
1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      initialized_(false) {
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LogPrivateAPI::~LogPrivateAPI() {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::StartNetInternalsWatch(
1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& extension_id,
1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    api::log_private::EventSink event_sink,
1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Closure& closure) {
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net_internal_watches_.insert(extension_id);
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Nuke any leftover app-specific or dumped log files from previous sessions.
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  BrowserThread::PostTaskAndReply(
1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      BrowserThread::IO,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging,
1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 base::Unretained(this),
1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 extension_id,
1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 g_browser_process->io_thread(),
1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 event_sink),
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      closure);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id,
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          const base::Closure& closure) {
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net_internal_watches_.erase(extension_id);
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MaybeStopNetInternalLogging(closure);
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::StopAllWatches(const std::string& extension_id,
1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   const base::Closure& closure) {
1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  StopNetInternalsWatch(extension_id, closure);
1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::RegisterTempFile(const std::string& owner_extension_id,
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                     const base::FilePath& file_path) {
1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!IsRunningOnSequenceThread()) {
1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GetSequencedTaskRunner()->PostTask(
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        FROM_HERE,
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&LogPrivateAPI::RegisterTempFile,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   base::Unretained(this),
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   owner_extension_id,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   file_path));
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  log_file_resources_.Add(new FileResource(owner_extension_id, file_path));
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> >
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    g_factory = LAZY_INSTANCE_INITIALIZER;
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<LogPrivateAPI>*
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)LogPrivateAPI::GetFactoryInstance() {
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return g_factory.Pointer();
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogPrivateAPI::OnAddEntry(const net::NetLog::Entry& entry) {
2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // We could receive events on whatever thread they happen to be generated,
2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // since we are only interested in network events, we should ignore any
2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // other thread than BrowserThread::IO.
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!pending_entries_.get()) {
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    pending_entries_.reset(new base::ListValue());
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostDelayedTask(
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&LogPrivateAPI::PostPendingEntries, base::Unretained(this)),
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds));
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  pending_entries_->Append(entry.ToValue());
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogPrivateAPI::PostPendingEntries() {
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&LogPrivateAPI:: AddEntriesOnUI,
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this),
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Passed(&pending_entries_)));
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) {
243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<std::string>::iterator ix = net_internal_watches_.begin();
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ix != net_internal_watches_.end(); ++ix) {
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Create the event's arguments value.
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> event_args(new base::ListValue());
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    event_args->Append(value->DeepCopy());
2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<Event> event(
2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        new Event(events::kOnCapturedEvents, event_args.Pass()));
2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EventRouter::Get(browser_context_)
2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ->DispatchEventToExtension(*ix, event.Pass());
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::InitializeNetLogger(const std::string& owner_extension_id,
2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                        net::NetLogLogger** net_log_logger) {
2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(IsRunningOnSequenceThread());
2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  (*net_log_logger) = NULL;
2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Create app-specific subdirectory in session logs folder.
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath app_log_dir = GetAppLogDirectory().Append(owner_extension_id);
2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!base::DirectoryExists(app_log_dir)) {
2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!base::CreateDirectory(app_log_dir)) {
2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LOG(ERROR) << "Could not create dir " << app_log_dir.value();
2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::FilePath file_path = app_log_dir.Append(kLogFileNameBase);
2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  file_path = logging::GenerateTimestampedName(file_path, base::Time::Now());
2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  FILE* file = NULL;
2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  file = fopen(file_path.value().c_str(), "w");
2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (file == NULL) {
2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Could not open " << file_path.value();
2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  RegisterTempFile(owner_extension_id, file_path);
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::Value> constants(net::NetLogLogger::GetConstants());
2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  *net_log_logger = new net::NetLogLogger(file, *constants);
2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  (*net_log_logger)->set_log_level(net::NetLog::LOG_ALL_BUT_BYTES);
2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::StartObservingNetEvents(
2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IOThread* io_thread,
2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    net::NetLogLogger** net_log_logger) {
2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!(*net_log_logger))
2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net_log_logger_.reset(*net_log_logger);
2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net_log_logger_->StartObserving(io_thread->net_log());
2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::MaybeStartNetInternalLogging(
2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& caller_extension_id,
2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    IOThread* io_thread,
3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    api::log_private::EventSink event_sink) {
301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!logging_net_internals_) {
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    logging_net_internals_ = true;
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    event_sink_ = event_sink;
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    switch (event_sink_) {
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_CAPTURE: {
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        io_thread->net_log()->AddThreadSafeObserver(
3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            this, net::NetLog::LOG_ALL_BUT_BYTES);
3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_FILE: {
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        net::NetLogLogger** net_logger_ptr = new net::NetLogLogger* [1];
3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // Initialize net logger on the blocking pool and start observing event
3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        // with in on IO thread.
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        GetSequencedTaskRunner()->PostTaskAndReply(
3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            FROM_HERE,
3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base::Bind(&LogPrivateAPI::InitializeNetLogger,
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       base::Unretained(this),
3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       caller_extension_id,
3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       net_logger_ptr),
3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            base::Bind(&LogPrivateAPI::StartObservingNetEvents,
3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       base::Unretained(this),
3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       io_thread,
3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       base::Owned(net_logger_ptr)));
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_NONE: {
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NOTREACHED();
3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::MaybeStopNetInternalLogging(const base::Closure& closure) {
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (net_internal_watches_.empty()) {
3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (closure.is_null()) {
3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      BrowserThread::PostTask(
3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          BrowserThread::IO,
3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          FROM_HERE,
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::Bind(&LogPrivateAPI::StopNetInternalLogging,
3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     base::Unretained(this)));
3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      BrowserThread::PostTaskAndReply(
3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          BrowserThread::IO,
3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          FROM_HERE,
3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::Bind(&LogPrivateAPI::StopNetInternalLogging,
3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     base::Unretained(this)),
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          closure);
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void LogPrivateAPI::StopNetInternalLogging() {
355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (net_log() && logging_net_internals_) {
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    logging_net_internals_ = false;
3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    switch (event_sink_) {
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_CAPTURE:
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        net_log()->RemoveThreadSafeObserver(this);
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_FILE:
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        net_log_logger_->StopObserving();
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        net_log_logger_.reset();
3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      case api::log_private::EVENT_SINK_NONE:
3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        NOTREACHED();
3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        break;
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateAPI::Initialize() {
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (initialized_)
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Clean up temp files and folders from the previous sessions.
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  initialized_ = true;
3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetSequencedTaskRunner()->PostTask(
3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FROM_HERE,
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&CleanUpLeftoverLogs,
3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 Profile::FromBrowserContext(browser_context_) ==
3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                     ProfileManager::GetPrimaryUserProfile(),
3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 GetAppLogDirectory(),
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 GetLogDumpDirectory(browser_context_)));
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid LogPrivateAPI::OnExtensionUnloaded(
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    content::BrowserContext* browser_context,
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const Extension* extension,
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    UnloadedExtensionInfo::Reason reason) {
3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  StopNetInternalsWatch(extension->id(), base::Closure());
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
396bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochLogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() {
397bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
398bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
399bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochLogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() {
400bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
401bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
402010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool LogPrivateGetHistoricalFunction::RunAsync() {
403bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Get parameters
404bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  scoped_ptr<api::log_private::GetHistorical::Params> params(
405bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      api::log_private::GetHistorical::Params::Create(*args_));
406bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  EXTENSION_FUNCTION_VALIDATE(params.get());
407bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  filter_handler_.reset(new FilterHandler(params->filter));
408bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  system_logs::SystemLogsFetcherBase* fetcher;
4103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if ((params->filter).scrub) {
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    fetcher = new system_logs::ScrubbedSystemLogsFetcher();
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else {
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    fetcher = new system_logs::AboutSystemLogsFetcher();
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
415bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  fetcher->Fetch(
416bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      base::Bind(&LogPrivateGetHistoricalFunction::OnSystemLogsLoaded, this));
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
418bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  return true;
419bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
420bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
421bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid LogPrivateGetHistoricalFunction::OnSystemLogsLoaded(
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<system_logs::SystemLogsResponse> sys_info) {
423bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  std::vector<linked_ptr<api::log_private::LogEntry> > data;
424bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
425bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  CollectLogInfo(filter_handler_.get(), sys_info.get(), &data);
426bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
427bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  // Prepare result
428bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  api::log_private::Result result;
429bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  result.data = data;
430bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  api::log_private::Filter::Populate(
431bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      *((filter_handler_->GetFilter())->ToValue()), &result.filter);
432bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  SetResult(result.ToValue().release());
433bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  SendResponse(true);
434bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
435bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateStartEventRecorderFunction::LogPrivateStartEventRecorderFunction() {
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateStartEventRecorderFunction::~LogPrivateStartEventRecorderFunction() {
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool LogPrivateStartEventRecorderFunction::RunAsync() {
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<api::log_private::StartEventRecorder::Params> params(
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      api::log_private::StartEventRecorder::Params::Create(*args_));
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (params->event_type) {
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case api::log_private::EVENT_TYPE_NETWORK:
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ->StartNetInternalsWatch(
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              extension_id(),
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              params->sink,
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              base::Bind(
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &LogPrivateStartEventRecorderFunction::OnEventRecorderStarted,
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  this));
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case api::log_private::EVENT_TYPE_NONE:
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED();
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return false;
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateStartEventRecorderFunction::OnEventRecorderStarted() {
4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SendResponse(true);
4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateStopEventRecorderFunction::LogPrivateStopEventRecorderFunction() {
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateStopEventRecorderFunction::~LogPrivateStopEventRecorderFunction() {
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool LogPrivateStopEventRecorderFunction::RunAsync() {
4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<api::log_private::StopEventRecorder::Params> params(
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      api::log_private::StopEventRecorder::Params::Create(*args_));
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXTENSION_FUNCTION_VALIDATE(params.get());
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (params->event_type) {
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case api::log_private::EVENT_TYPE_NETWORK:
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ->StopNetInternalsWatch(
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              extension_id(),
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              base::Bind(
4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  &LogPrivateStopEventRecorderFunction::OnEventRecorderStopped,
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                  this));
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case api::log_private::EVENT_TYPE_NONE:
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED();
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return false;
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateStopEventRecorderFunction::OnEventRecorderStopped() {
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SendResponse(true);
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateDumpLogsFunction::LogPrivateDumpLogsFunction() {
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LogPrivateDumpLogsFunction::~LogPrivateDumpLogsFunction() {
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool LogPrivateDumpLogsFunction::RunAsync() {
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ->StopAllWatches(
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extension_id(),
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::Bind(&LogPrivateDumpLogsFunction::OnStopAllWatches, this));
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateDumpLogsFunction::OnStopAllWatches() {
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  chromeos::DebugLogWriter::StoreCombinedLogs(
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetLogDumpDirectory(browser_context()).Append(extension_id()),
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      FileResource::kSequenceToken,
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&LogPrivateDumpLogsFunction::OnStoreLogsCompleted, this));
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void LogPrivateDumpLogsFunction::OnStoreLogsCompleted(
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::FilePath& log_path,
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool succeeded) {
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (succeeded) {
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context()))
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ->RegisterTempFile(extension_id(), log_path);
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue());
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  extensions::GrantedFileEntry file_entry =
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      extensions::app_file_handler_util::CreateFileEntry(
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          Profile::FromBrowserContext(browser_context()),
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extension(),
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          render_view_host_->GetProcess()->GetID(),
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          log_path,
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          false);
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::DictionaryValue* entry = new base::DictionaryValue();
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entry->SetString("fileSystemId", file_entry.filesystem_id);
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entry->SetString("baseName", file_entry.registered_name);
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entry->SetString("id", file_entry.id);
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entry->SetBoolean("isDirectory", false);
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::ListValue* entry_list = new base::ListValue();
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  entry_list->Append(entry);
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  response->Set("entries", entry_list);
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  response->SetBoolean("multiple", false);
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SetResult(response.release());
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  SendResponse(succeeded);
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
549bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}  // namespace extensions
550