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.
5 #include "chrome/browser/chromeos/system_logs/debug_daemon_log_source.h"
8 #include "base/bind_helpers.h"
9 #include "base/files/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/profiles/profile_helper.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 "components/user_manager/user.h"
20 #include "components/user_manager/user_manager.h"
21 #include "content/public/browser/browser_thread.h"
23 const char kNotAvailable
[] = "<not available>";
24 const char kRoutesKeyName
[] = "routes";
25 const char kNetworkStatusKeyName
[] = "network-status";
26 const char kModemStatusKeyName
[] = "modem-status";
27 const char kWiMaxStatusKeyName
[] = "wimax-status";
28 const char kUserLogFileKeyName
[] = "user_log_files";
30 namespace system_logs
{
32 DebugDaemonLogSource::DebugDaemonLogSource(bool scrub
)
33 : SystemLogsSource("DebugDemon"),
34 response_(new SystemLogsResponse()),
35 num_pending_requests_(0),
37 weak_ptr_factory_(this) {}
39 DebugDaemonLogSource::~DebugDaemonLogSource() {}
41 void DebugDaemonLogSource::Fetch(const SysLogsSourceCallback
& callback
) {
42 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
43 DCHECK(!callback
.is_null());
44 DCHECK(callback_
.is_null());
47 chromeos::DebugDaemonClient
* client
=
48 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
50 client
->GetRoutes(true, // Numeric
52 base::Bind(&DebugDaemonLogSource::OnGetRoutes
,
53 weak_ptr_factory_
.GetWeakPtr()));
54 ++num_pending_requests_
;
55 client
->GetNetworkStatus(base::Bind(&DebugDaemonLogSource::OnGetNetworkStatus
,
56 weak_ptr_factory_
.GetWeakPtr()));
57 ++num_pending_requests_
;
58 client
->GetModemStatus(base::Bind(&DebugDaemonLogSource::OnGetModemStatus
,
59 weak_ptr_factory_
.GetWeakPtr()));
60 ++num_pending_requests_
;
61 client
->GetWiMaxStatus(base::Bind(&DebugDaemonLogSource::OnGetWiMaxStatus
,
62 weak_ptr_factory_
.GetWeakPtr()));
63 ++num_pending_requests_
;
64 client
->GetUserLogFiles(base::Bind(&DebugDaemonLogSource::OnGetUserLogFiles
,
65 weak_ptr_factory_
.GetWeakPtr()));
66 ++num_pending_requests_
;
69 client
->GetScrubbedLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs
,
70 weak_ptr_factory_
.GetWeakPtr()));
72 client
->GetAllLogs(base::Bind(&DebugDaemonLogSource::OnGetLogs
,
73 weak_ptr_factory_
.GetWeakPtr()));
75 ++num_pending_requests_
;
78 void DebugDaemonLogSource::OnGetRoutes(bool succeeded
,
79 const std::vector
<std::string
>& routes
) {
80 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
83 (*response_
)[kRoutesKeyName
] = JoinString(routes
, '\n');
85 (*response_
)[kRoutesKeyName
] = kNotAvailable
;
89 void DebugDaemonLogSource::OnGetNetworkStatus(bool succeeded
,
90 const std::string
& status
) {
91 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
94 (*response_
)[kNetworkStatusKeyName
] = status
;
96 (*response_
)[kNetworkStatusKeyName
] = kNotAvailable
;
100 void DebugDaemonLogSource::OnGetModemStatus(bool succeeded
,
101 const std::string
& status
) {
102 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
105 (*response_
)[kModemStatusKeyName
] = status
;
107 (*response_
)[kModemStatusKeyName
] = kNotAvailable
;
111 void DebugDaemonLogSource::OnGetWiMaxStatus(bool succeeded
,
112 const std::string
& status
) {
113 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
116 (*response_
)[kWiMaxStatusKeyName
] = status
;
118 (*response_
)[kWiMaxStatusKeyName
] = kNotAvailable
;
122 void DebugDaemonLogSource::OnGetLogs(bool /* succeeded */,
123 const KeyValueMap
& logs
) {
124 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
126 // We ignore 'succeeded' for this callback - we want to display as much of the
127 // debug info as we can even if we failed partway through parsing, and if we
128 // couldn't fetch any of it, none of the fields will even appear.
129 response_
->insert(logs
.begin(), logs
.end());
133 void DebugDaemonLogSource::OnGetUserLogFiles(
135 const KeyValueMap
& user_log_files
) {
136 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
138 SystemLogsResponse
* response
= new SystemLogsResponse
;
140 const user_manager::UserList
& users
=
141 user_manager::UserManager::Get()->GetLoggedInUsers();
142 std::vector
<base::FilePath
> profile_dirs
;
143 for (user_manager::UserList::const_iterator it
= users
.begin();
146 if ((*it
)->username_hash().empty())
148 profile_dirs
.push_back(
149 chromeos::ProfileHelper::GetProfilePathByUserIdHash(
150 (*it
)->username_hash()));
153 content::BrowserThread::PostBlockingPoolTaskAndReply(
155 base::Bind(&DebugDaemonLogSource::ReadUserLogFiles
,
156 user_log_files
, profile_dirs
, response
),
157 base::Bind(&DebugDaemonLogSource::MergeResponse
,
158 weak_ptr_factory_
.GetWeakPtr(),
159 base::Owned(response
)));
161 (*response_
)[kUserLogFileKeyName
] = kNotAvailable
;
167 void DebugDaemonLogSource::ReadUserLogFiles(
168 const KeyValueMap
& user_log_files
,
169 const std::vector
<base::FilePath
>& profile_dirs
,
170 SystemLogsResponse
* response
) {
171 for (size_t i
= 0; i
< profile_dirs
.size(); ++i
) {
172 std::string profile_prefix
= "Profile[" + base::UintToString(i
) + "] ";
173 for (KeyValueMap::const_iterator it
= user_log_files
.begin();
174 it
!= user_log_files
.end();
176 std::string key
= it
->first
;
178 std::string filename
= it
->second
;
179 bool read_success
= base::ReadFileToString(
180 profile_dirs
[i
].Append(filename
), &value
);
182 if (read_success
&& !value
.empty())
183 (*response
)[profile_prefix
+ key
] = value
;
185 (*response
)[profile_prefix
+ filename
] = kNotAvailable
;
190 void DebugDaemonLogSource::MergeResponse(SystemLogsResponse
* response
) {
191 for (SystemLogsResponse::const_iterator it
= response
->begin();
192 it
!= response
->end(); ++it
)
193 response_
->insert(*it
);
197 void DebugDaemonLogSource::RequestCompleted() {
198 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
199 DCHECK(!callback_
.is_null());
201 --num_pending_requests_
;
202 if (num_pending_requests_
> 0)
204 callback_
.Run(response_
.get());
207 } // namespace system_logs