// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/cros/syslogs_library.h" #include "base/command_line.h" #include "base/file_util.h" #include "base/string_util.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/common/chrome_switches.h" #include "content/browser/browser_thread.h" namespace chromeos { const char kContextFeedback[] = "feedback"; const char kContextSysInfo[] = "sysinfo"; class SyslogsLibraryImpl : public SyslogsLibrary { public: SyslogsLibraryImpl() {} virtual ~SyslogsLibraryImpl() {} virtual Handle RequestSyslogs( bool compress_logs, bool add_feedback_context, CancelableRequestConsumerBase* consumer, ReadCompleteCallback* callback); // Reads system logs, compresses content if requested. // Called from FILE thread. void ReadSyslogs( scoped_refptr<CancelableRequest<ReadCompleteCallback> > request, bool compress_logs, bool add_feedback_context); void LoadCompressedLogs(const FilePath& zip_file, std::string* zip_content); DISALLOW_COPY_AND_ASSIGN(SyslogsLibraryImpl); }; class SyslogsLibraryStubImpl : public SyslogsLibrary { public: SyslogsLibraryStubImpl() {} virtual ~SyslogsLibraryStubImpl() {} virtual Handle RequestSyslogs(bool compress_logs, bool add_feedback_context, CancelableRequestConsumerBase* consumer, ReadCompleteCallback* callback) { if (callback) callback->Run(Tuple2<LogDictionaryType*, std::string*>(NULL , NULL)); return 0; } }; // static SyslogsLibrary* SyslogsLibrary::GetImpl(bool stub) { if (stub) return new SyslogsLibraryStubImpl(); else return new SyslogsLibraryImpl(); } CancelableRequestProvider::Handle SyslogsLibraryImpl::RequestSyslogs( bool compress_logs, bool add_feedback_context, CancelableRequestConsumerBase* consumer, ReadCompleteCallback* callback) { // Register the callback request. scoped_refptr<CancelableRequest<ReadCompleteCallback> > request( new CancelableRequest<ReadCompleteCallback>(callback)); AddRequest(request, consumer); // Schedule a task on the FILE thread which will then trigger a request // callback on the calling thread (e.g. UI) when complete. BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod( this, &SyslogsLibraryImpl::ReadSyslogs, request, compress_logs, add_feedback_context)); return request->handle(); } // Called from FILE thread. void SyslogsLibraryImpl::ReadSyslogs( scoped_refptr<CancelableRequest<ReadCompleteCallback> > request, bool compress_logs, bool add_feedback_context) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); if (request->canceled()) return; if (compress_logs && !CommandLine::ForCurrentProcess()->HasSwitch( switches::kCompressSystemFeedback)) compress_logs = false; // Create temp file. FilePath zip_file; if (compress_logs && !file_util::CreateTemporaryFile(&zip_file)) { LOG(ERROR) << "Cannot create temp file"; compress_logs = false; } LogDictionaryType* logs = NULL; if (CrosLibrary::Get()->EnsureLoaded()) logs = chromeos::GetSystemLogs( compress_logs ? &zip_file : NULL, add_feedback_context ? kContextFeedback : kContextSysInfo); std::string* zip_content = NULL; if (compress_logs) { // Load compressed logs. zip_content = new std::string(); LoadCompressedLogs(zip_file, zip_content); file_util::Delete(zip_file, false); } // Will call the callback on the calling thread. request->ForwardResult(Tuple2<LogDictionaryType*, std::string*>(logs, zip_content)); } void SyslogsLibraryImpl::LoadCompressedLogs(const FilePath& zip_file, std::string* zip_content) { DCHECK(zip_content); if (!file_util::ReadFileToString(zip_file, zip_content)) { LOG(ERROR) << "Cannot read compressed logs file from " << zip_file.value().c_str(); } } } // namespace chromeos // Allows InvokeLater without adding refcounting. SyslogsLibraryImpl is a // Singleton and won't be deleted until it's last InvokeLater is run. DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::SyslogsLibraryImpl);