debug_daemon_log_source.cc revision 5e3f23d412006dc4db4e659864679f29341e113f
1// Copyright (c) 2012 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/chromeos/system_logs/debug_daemon_log_source.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/file_util.h"
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/weak_ptr.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/string_util.h"
15#include "chrome/browser/chromeos/system_logs/system_logs_fetcher.h"
16#include "chrome/browser/profiles/profile_manager.h"
17#include "chrome/common/chrome_switches.h"
18#include "chromeos/dbus/dbus_thread_manager.h"
19#include "chromeos/dbus/debug_daemon_client.h"
20#include "content/public/browser/browser_thread.h"
21
22const char kNotAvailable[] = "<not available>";
23const char kRoutesKeyName[] = "routes";
24const char kNetworkStatusKeyName[] = "network-status";
25const char kModemStatusKeyName[] = "modem-status";
26const char kUserLogFileKeyName[] = "user_log_files";
27
28namespace chromeos {
29
30DebugDaemonLogSource::DebugDaemonLogSource()
31    : response_(new SystemLogsResponse()),
32      num_pending_requests_(0),
33      weak_ptr_factory_(this) {}
34
35DebugDaemonLogSource::~DebugDaemonLogSource() {}
36
37void DebugDaemonLogSource::Fetch(const SysLogsSourceCallback& callback) {
38  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
39  DCHECK(!callback.is_null());
40  DCHECK(callback_.is_null());
41
42  callback_ = callback;
43  DebugDaemonClient* client = DBusThreadManager::Get()->GetDebugDaemonClient();
44
45  client->GetRoutes(true,   // Numeric
46                    false,  // No IPv6
47                    base::Bind(&DebugDaemonLogSource::OnGetRoutes,
48                               weak_ptr_factory_.GetWeakPtr()));
49  ++num_pending_requests_;
50  client->GetNetworkStatus(base::Bind(&DebugDaemonLogSource::OnGetNetworkStatus,
51                                      weak_ptr_factory_.GetWeakPtr()));
52  ++num_pending_requests_;
53  client->GetModemStatus(base::Bind(&DebugDaemonLogSource::OnGetModemStatus,
54                                    weak_ptr_factory_.GetWeakPtr()));
55  ++num_pending_requests_;
56  client->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
57                                weak_ptr_factory_.GetWeakPtr()));
58  ++num_pending_requests_;
59  client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
60                                     weak_ptr_factory_.GetWeakPtr()));
61  ++num_pending_requests_;
62}
63
64void DebugDaemonLogSource::OnGetRoutes(bool succeeded,
65                                       const std::vector<std::string>& routes) {
66  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
67
68  if (succeeded)
69    (*response_)[kRoutesKeyName] = JoinString(routes, '\n');
70  else
71    (*response_)[kRoutesKeyName] = kNotAvailable;
72  RequestCompleted();
73}
74
75void DebugDaemonLogSource::OnGetNetworkStatus(bool succeeded,
76                                              const std::string& status) {
77  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
78
79  if (succeeded)
80    (*response_)[kNetworkStatusKeyName] = status;
81  else
82    (*response_)[kNetworkStatusKeyName] = kNotAvailable;
83  RequestCompleted();
84}
85
86void DebugDaemonLogSource::OnGetModemStatus(bool succeeded,
87                                            const std::string& status) {
88  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
89
90  if (succeeded)
91    (*response_)[kModemStatusKeyName] = status;
92  else
93    (*response_)[kModemStatusKeyName] = kNotAvailable;
94  RequestCompleted();
95}
96
97void DebugDaemonLogSource::OnGetLogs(bool /* succeeded */,
98                                     const KeyValueMap& logs) {
99  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
100
101  // We ignore 'succeeded' for this callback - we want to display as much of the
102  // debug info as we can even if we failed partway through parsing, and if we
103  // couldn't fetch any of it, none of the fields will even appear.
104  response_->insert(logs.begin(), logs.end());
105  RequestCompleted();
106}
107
108void DebugDaemonLogSource::OnGetUserLogFiles(
109    bool succeeded,
110    const KeyValueMap& user_log_files) {
111  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
112  if (succeeded) {
113    content::BrowserThread::PostBlockingPoolTaskAndReply(
114        FROM_HERE,
115        base::Bind(
116            &DebugDaemonLogSource::ReadUserLogFiles,
117            weak_ptr_factory_.GetWeakPtr(),
118            user_log_files),
119        base::Bind(&DebugDaemonLogSource::RequestCompleted,
120                   weak_ptr_factory_.GetWeakPtr()));
121  } else {
122    (*response_)[kUserLogFileKeyName] = kNotAvailable;
123    RequestCompleted();
124  }
125}
126
127void DebugDaemonLogSource::ReadUserLogFiles(const KeyValueMap& user_log_files) {
128  std::vector<Profile*> last_used = ProfileManager::GetLastOpenedProfiles();
129
130  for (size_t i = 0; i < last_used.size(); ++i) {
131    std::string profile_prefix = "Profile[" + base::UintToString(i) + "] ";
132    for (KeyValueMap::const_iterator it = user_log_files.begin();
133         it != user_log_files.end();
134         ++it) {
135      std::string key = it->first;
136      std::string value;
137      std::string filename = it->second;
138      base::FilePath profile_dir = last_used[i]->GetPath();
139      bool read_success = file_util::ReadFileToString(
140          profile_dir.Append(filename), &value);
141
142      if (read_success && !value.empty())
143        (*response_)[profile_prefix + key] = value;
144      else
145        (*response_)[profile_prefix + filename] = kNotAvailable;
146    }
147  }
148}
149
150void DebugDaemonLogSource::RequestCompleted() {
151  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
152  DCHECK(!callback_.is_null());
153
154  --num_pending_requests_;
155  if (num_pending_requests_ > 0)
156    return;
157  callback_.Run(response_.get());
158}
159
160}  // namespace chromeos
161