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