debug_daemon_log_source.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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 kWiMaxStatusKeyName[] = "wimax-status";
27const char kUserLogFileKeyName[] = "user_log_files";
28
29namespace chromeos {
30
31DebugDaemonLogSource::DebugDaemonLogSource()
32    : response_(new SystemLogsResponse()),
33      num_pending_requests_(0),
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->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs,
61                                weak_ptr_factory_.GetWeakPtr()));
62  ++num_pending_requests_;
63  client->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles,
64                                     weak_ptr_factory_.GetWeakPtr()));
65  ++num_pending_requests_;
66}
67
68void DebugDaemonLogSource::OnGetRoutes(bool succeeded,
69                                       const std::vector<std::string>& routes) {
70  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
71
72  if (succeeded)
73    (*response_)[kRoutesKeyName] = JoinString(routes, '\n');
74  else
75    (*response_)[kRoutesKeyName] = kNotAvailable;
76  RequestCompleted();
77}
78
79void DebugDaemonLogSource::OnGetNetworkStatus(bool succeeded,
80                                              const std::string& status) {
81  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
82
83  if (succeeded)
84    (*response_)[kNetworkStatusKeyName] = status;
85  else
86    (*response_)[kNetworkStatusKeyName] = kNotAvailable;
87  RequestCompleted();
88}
89
90void DebugDaemonLogSource::OnGetModemStatus(bool succeeded,
91                                            const std::string& status) {
92  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
93
94  if (succeeded)
95    (*response_)[kModemStatusKeyName] = status;
96  else
97    (*response_)[kModemStatusKeyName] = kNotAvailable;
98  RequestCompleted();
99}
100
101void DebugDaemonLogSource::OnGetWiMaxStatus(bool succeeded,
102                                            const std::string& status) {
103  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
104
105  if (succeeded)
106    (*response_)[kWiMaxStatusKeyName] = status;
107  else
108    (*response_)[kWiMaxStatusKeyName] = kNotAvailable;
109  RequestCompleted();
110}
111
112void DebugDaemonLogSource::OnGetLogs(bool /* succeeded */,
113                                     const KeyValueMap& logs) {
114  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
115
116  // We ignore 'succeeded' for this callback - we want to display as much of the
117  // debug info as we can even if we failed partway through parsing, and if we
118  // couldn't fetch any of it, none of the fields will even appear.
119  response_->insert(logs.begin(), logs.end());
120  RequestCompleted();
121}
122
123void DebugDaemonLogSource::OnGetUserLogFiles(
124    bool succeeded,
125    const KeyValueMap& user_log_files) {
126  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
127  if (succeeded) {
128    SystemLogsResponse* response = new SystemLogsResponse;
129    std::vector<Profile*> last_used = ProfileManager::GetLastOpenedProfiles();
130    content::BrowserThread::PostBlockingPoolTaskAndReply(
131        FROM_HERE,
132        base::Bind(&DebugDaemonLogSource::ReadUserLogFiles,
133                   user_log_files, last_used, response),
134        base::Bind(&DebugDaemonLogSource::MergeResponse,
135                   weak_ptr_factory_.GetWeakPtr(),
136                   base::Owned(response)));
137  } else {
138    (*response_)[kUserLogFileKeyName] = kNotAvailable;
139    RequestCompleted();
140  }
141}
142
143// static
144void DebugDaemonLogSource::ReadUserLogFiles(
145    const KeyValueMap& user_log_files,
146    const std::vector<Profile*>& last_used_profiles,
147    SystemLogsResponse* response) {
148  for (size_t i = 0; i < last_used_profiles.size(); ++i) {
149    std::string profile_prefix = "Profile[" + base::UintToString(i) + "] ";
150    for (KeyValueMap::const_iterator it = user_log_files.begin();
151         it != user_log_files.end();
152         ++it) {
153      std::string key = it->first;
154      std::string value;
155      std::string filename = it->second;
156      base::FilePath profile_dir = last_used_profiles[i]->GetPath();
157      bool read_success = file_util::ReadFileToString(
158          profile_dir.Append(filename), &value);
159
160      if (read_success && !value.empty())
161        (*response)[profile_prefix + key] = value;
162      else
163        (*response)[profile_prefix + filename] = kNotAvailable;
164    }
165  }
166}
167
168void DebugDaemonLogSource::MergeResponse(SystemLogsResponse* response) {
169  for (SystemLogsResponse::const_iterator it = response->begin();
170       it != response->end(); ++it)
171    response_->insert(*it);
172  RequestCompleted();
173}
174
175void DebugDaemonLogSource::RequestCompleted() {
176  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
177  DCHECK(!callback_.is_null());
178
179  --num_pending_requests_;
180  if (num_pending_requests_ > 0)
181    return;
182  callback_.Run(response_.get());
183}
184
185}  // namespace chromeos
186