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