15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/chromeos/profiles/profile_helper.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/dbus/debug_daemon_client.h"
1903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "components/user_manager/user.h"
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNotAvailable[] = "<not available>";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRoutesKeyName[] = "routes";
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNetworkStatusKeyName[] = "network-status";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kModemStatusKeyName[] = "modem-status";
2758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochconst char kWiMaxStatusKeyName[] = "wimax-status";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kUserLogFileKeyName[] = "user_log_files";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace system_logs {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochDebugDaemonLogSource::DebugDaemonLogSource(bool scrub)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : response_(new SystemLogsResponse()),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_pending_requests_(0),
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      scrub_(scrub),
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DebugDaemonLogSource::~DebugDaemonLogSource() {}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::Fetch(const SysLogsSourceCallback& callback) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_.is_null());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chromeos::DebugDaemonClient* client =
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->GetRoutes(true,   // Numeric
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    false,  // No IPv6
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    base::Bind(&DebugDaemonLogSource::OnGetRoutes,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               weak_ptr_factory_.GetWeakPtr()));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_requests_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->GetNetworkStatus(base::Bind(&DebugDaemonLogSource::OnGetNetworkStatus,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      weak_ptr_factory_.GetWeakPtr()));
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_requests_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->GetModemStatus(base::Bind(&DebugDaemonLogSource::OnGetModemStatus,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    weak_ptr_factory_.GetWeakPtr()));
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_requests_;
6058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  client->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus,
6158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch                                    weak_ptr_factory_.GetWeakPtr()));
6258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  ++num_pending_requests_;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     weak_ptr_factory_.GetWeakPtr()));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++num_pending_requests_;
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (scrub_) {
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    client->GetScrubbedLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                       weak_ptr_factory_.GetWeakPtr()));
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  weak_ptr_factory_.GetWeakPtr()));
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ++num_pending_requests_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::OnGetRoutes(bool succeeded,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::vector<std::string>& routes) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kRoutesKeyName] = JoinString(routes, '\n');
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kRoutesKeyName] = kNotAvailable;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestCompleted();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::OnGetNetworkStatus(bool succeeded,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const std::string& status) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kNetworkStatusKeyName] = status;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kNetworkStatusKeyName] = kNotAvailable;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestCompleted();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::OnGetModemStatus(bool succeeded,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            const std::string& status) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kModemStatusKeyName] = status;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kModemStatusKeyName] = kNotAvailable;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestCompleted();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochvoid DebugDaemonLogSource::OnGetWiMaxStatus(bool succeeded,
11158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch                                            const std::string& status) {
11258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
11358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
11458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  if (succeeded)
11558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    (*response_)[kWiMaxStatusKeyName] = status;
11658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  else
11758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    (*response_)[kWiMaxStatusKeyName] = kNotAvailable;
11858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch  RequestCompleted();
11958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}
12058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::OnGetLogs(bool /* succeeded */,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const KeyValueMap& logs) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We ignore 'succeeded' for this callback - we want to display as much of the
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // debug info as we can even if we failed partway through parsing, and if we
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // couldn't fetch any of it, none of the fields will even appear.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_->insert(logs.begin(), logs.end());
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RequestCompleted();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::OnGetUserLogFiles(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool succeeded,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const KeyValueMap& user_log_files) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (succeeded) {
1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SystemLogsResponse* response = new SystemLogsResponse;
13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
13903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const user_manager::UserList& users =
14003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        user_manager::UserManager::Get()->GetLoggedInUsers();
14103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<base::FilePath> profile_dirs;
14203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    for (user_manager::UserList::const_iterator it = users.begin();
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         it != users.end();
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)         ++it) {
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      if ((*it)->username_hash().empty())
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        continue;
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      profile_dirs.push_back(
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          chromeos::ProfileHelper::GetProfilePathByUserIdHash(
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              (*it)->username_hash()));
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::BrowserThread::PostBlockingPoolTaskAndReply(
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&DebugDaemonLogSource::ReadUserLogFiles,
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                   user_log_files, profile_dirs, response),
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        base::Bind(&DebugDaemonLogSource::MergeResponse,
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                   base::Owned(response)));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*response_)[kUserLogFileKeyName] = kNotAvailable;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestCompleted();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// static
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void DebugDaemonLogSource::ReadUserLogFiles(
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const KeyValueMap& user_log_files,
16803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    const std::vector<base::FilePath>& profile_dirs,
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    SystemLogsResponse* response) {
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  for (size_t i = 0; i < profile_dirs.size(); ++i) {
171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    std::string profile_prefix = "Profile[" + base::UintToString(i) + "] ";
172b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    for (KeyValueMap::const_iterator it = user_log_files.begin();
173b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         it != user_log_files.end();
174b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)         ++it) {
175b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      std::string key = it->first;
176b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      std::string value;
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      std::string filename = it->second;
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      bool read_success = base::ReadFileToString(
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          profile_dirs[i].Append(filename), &value);
180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      if (read_success && !value.empty())
1823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*response)[profile_prefix + key] = value;
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      else
1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        (*response)[profile_prefix + filename] = kNotAvailable;
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void DebugDaemonLogSource::MergeResponse(SystemLogsResponse* response) {
1903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (SystemLogsResponse::const_iterator it = response->begin();
1913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       it != response->end(); ++it)
1923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    response_->insert(*it);
1933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RequestCompleted();
1943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DebugDaemonLogSource::RequestCompleted() {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_.is_null());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --num_pending_requests_;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_pending_requests_ > 0)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(response_.get());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace system_logs
207