Chromium Code Reviews| Index: chrome/browser/webrtc_log_upload_manager.cc |
| diff --git a/chrome/browser/webrtc_log_upload_manager.cc b/chrome/browser/webrtc_log_upload_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b646af0401dd73dac16a8640b3968c07d7b94ede |
| --- /dev/null |
| +++ b/chrome/browser/webrtc_log_upload_manager.cc |
| @@ -0,0 +1,243 @@ |
| +// Copyright (c) 2013 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/webrtc_log_upload_manager.h" |
| + |
| +#if defined(USE_SYSTEM_LIBBZ2) |
| +#include <bzlib.h> |
| +#else |
| +#include "third_party/bzip2/bzlib.h" |
| +#endif |
| + |
| +#include "base/bind.h" |
| +#include "base/command_line.h" |
| +#include "base/prefs/pref_service.h" |
| +#include "base/logging.h" |
| +#include "chrome/browser/browser_process.h" |
|
Jói
2013/04/26 12:55:10
Where is this used?
|
| +#include "chrome/common/cloud_print/cloud_print_helpers.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "content/browser/browser_thread_impl.h" |
| +#include "content/common/partial_circular_buffer.h" |
| +#include "googleurl/src/gurl.h" |
| +#include "net/base/file_stream.h" |
| +#include "net/proxy/proxy_config_service.h" |
| +#include "net/url_request/url_fetcher.h" |
| +#include "net/url_request/url_request_context_builder.h" |
| + |
| +const uint32 kIntermediateCompressionBufferSize = 0.5 * 1024 * 1024; // 0.5 MB |
| + |
| +const char kTempUploadFile[] = "/tmp/chromium-upload-webrtc-log"; |
| +const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| +const char kUploadContentType[] = "multipart/form-data"; |
| +const char kMultipartBoundary[] = |
| + "----**--yradnuoBgoLtrapitluMklaTelgooG--**----"; |
| + |
| +namespace { |
| + |
| +// Config getter that always returns direct settings. |
| +class ProxyConfigServiceDirect : public net::ProxyConfigService { |
| + public: |
| + // ProxyConfigService implementation. |
| + virtual void AddObserver(Observer* observer) OVERRIDE {} |
| + virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
| + virtual ConfigAvailability GetLatestProxyConfig( |
| + net::ProxyConfig* config) OVERRIDE { |
| + *config = net::ProxyConfig::CreateDirect(); |
| + return CONFIG_VALID; |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| +class WebRtcLogURLRequestContextGetter : |
| + public net::URLRequestContextGetter { |
| + public: |
| + WebRtcLogURLRequestContextGetter() {} |
| + |
| + // net::URLRequestContextGetter implementation. |
| + virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| + |
| + if (!url_request_context_) { |
| + net::URLRequestContextBuilder builder; |
| +#if defined(OS_LINUX) || defined(OS_ANDROID) |
| + builder.set_proxy_config_service(new ProxyConfigServiceDirect()); |
| +#endif |
| + url_request_context_.reset(builder.Build()); |
| + } |
| + CHECK(url_request_context_.get()); |
| + |
| + return url_request_context_.get(); |
| + } |
| + |
| + virtual scoped_refptr<base::SingleThreadTaskRunner> |
| + GetNetworkTaskRunner() const OVERRIDE { |
| + return content::BrowserThread::GetMessageLoopProxyForThread( |
| + content::BrowserThread::IO); |
| + } |
| + |
| + private: |
| + virtual ~WebRtcLogURLRequestContextGetter() {} |
| + |
| + // NULL if not yet initialized. Otherwise, it is the URLRequestContext |
| + // instance that was lazily created by GetURLRequestContext(). |
| + // Access only from the IO thread. |
| + scoped_ptr<net::URLRequestContext> url_request_context_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(WebRtcLogURLRequestContextGetter); |
| +}; |
| + |
| + |
| +WebRtcLogUploadManager::WebRtcLogUploadManager() { |
| +} |
| + |
| +WebRtcLogUploadManager::~WebRtcLogUploadManager() { |
| +} |
| + |
| +void WebRtcLogUploadManager::OnURLFetchComplete( |
| + const net::URLFetcher* source) { |
| + std::vector<net::URLFetcher*>::iterator it; |
| + for (it = url_fetchers_.begin(); it != url_fetchers_.end(); ++it) { |
| + if (*it == source) { |
| + url_fetchers_.erase(it); |
| + break; |
| + } |
| + } |
| + delete source; |
| +} |
| + |
| +void WebRtcLogUploadManager::OnURLFetchUploadProgress( |
| + const net::URLFetcher* source, int64 current, int64 total) { |
| +} |
| + |
| +void WebRtcLogUploadManager::UploadLog(base::SharedMemory* shared_memory, |
| + uint32 length) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
| + DCHECK(shared_memory); |
| + DCHECK(shared_memory->memory()); |
| + |
| + scoped_ptr<base::SharedMemory> scoped_shared_memory(shared_memory); |
| + |
| + uint8 compressed[length]; |
| + uint32 compressed_size = sizeof(compressed); //content::kWebRtcLogSize; |
| + ReadAndCompressLog(reinterpret_cast<uint8*>(scoped_shared_memory->memory()), |
| + length, compressed, &compressed_size); |
| + |
| + SetupUpload(compressed, compressed_size); |
| + |
| + if (!request_context_getter_) |
| + request_context_getter_ = new WebRtcLogURLRequestContextGetter(); |
| + |
| + std::string content_type = kUploadContentType; |
| + content_type.append("; boundary="); |
| + content_type.append(kMultipartBoundary); |
| + |
| + net::URLFetcher* url_fetcher = |
| + net::URLFetcher::Create(GURL(kUploadURL), net::URLFetcher::POST, this); |
| +// url_fetcher_.reset( |
| +// net::URLFetcher::Create(GURL(kUploadURL), net::URLFetcher::POST, this)); |
| + url_fetcher->SetRequestContext(request_context_getter_); |
| + url_fetcher->SetUploadFilePath( |
| + content_type, base::FilePath(kTempUploadFile), |
| + content::BrowserThread::GetMessageLoopProxyForThread( |
| + content::BrowserThread::FILE)); |
| + url_fetcher->Start(); |
| + url_fetchers_.push_back(url_fetcher); |
| +} |
| + |
| +void WebRtcLogUploadManager::ReadAndCompressLog(uint8* input, |
| + uint32 input_size, |
| + uint8* output, |
| + uint32* output_size) { |
| + content::PartialCircularBuffer read_pcb(input, input_size); |
| + |
| + bz_stream stream = {0}; |
| + int result = BZ2_bzCompressInit(&stream, 6, 0, 0); |
| + DCHECK(result == BZ_OK); |
| + |
| + scoped_ptr<uint8[]> intermediate_buffer( |
| + new uint8[kIntermediateCompressionBufferSize]); |
| + memset(intermediate_buffer.get(), 0, kIntermediateCompressionBufferSize); |
| + uint32 read = read_pcb.Read(intermediate_buffer.get(), |
| + kIntermediateCompressionBufferSize); |
| + stream.next_in = reinterpret_cast<char*>(&intermediate_buffer.get()[0]); |
| + stream.avail_in = read; |
| + |
| + while (read == kIntermediateCompressionBufferSize) { |
| + stream.next_out = |
| + reinterpret_cast<char*>(&((output)[stream.total_out_lo32])); |
| + stream.avail_out = *output_size - stream.total_out_lo32; |
| + result = BZ2_bzCompress(&stream, BZ_RUN); |
| + DCHECK(result == BZ_OK); |
| + read = read_pcb.Read(intermediate_buffer.get(), |
| + kIntermediateCompressionBufferSize); |
| + } |
| + |
| + stream.avail_in = read; |
| + do { |
| + stream.next_out = |
| + reinterpret_cast<char*>(&((output)[stream.total_out_lo32])); |
| + stream.avail_out = *output_size - stream.total_out_lo32; |
| + result = BZ2_bzCompress(&stream, BZ_FINISH); |
| + } while (result == BZ_FINISH_OK); |
| + DCHECK(result == BZ_STREAM_END); |
| + |
| + result = BZ2_bzCompressEnd(&stream); |
| + DCHECK(result == BZ_OK); |
| + |
| + *output_size = stream.total_out_lo32; |
| +} |
| + |
| +void WebRtcLogUploadManager::SetupUpload(uint8* log_data, |
| + uint32 log_data_size) { |
| + file_stream_.reset(new net::FileStream(NULL)); |
| + int open_flags = base::PLATFORM_FILE_CREATE_ALWAYS | |
| + base::PLATFORM_FILE_WRITE; |
| + file_stream_->OpenSync(base::FilePath(kTempUploadFile), |
| + open_flags); |
| + |
| + // TODO(grunell): Correct product name. |
| + AddPairString("prod", "Chrome"); |
| + // TODO(grunell): Correct version. |
| + AddPairString("ver", "0.0.1.1-dev-test"); |
| + AddPairString("type", "log"); |
| + |
| + AddUrlChunks(); |
| + |
| + AddLogData(log_data, log_data_size); |
| + |
| + std::stringstream ss; |
| + ss << "--" << kMultipartBoundary << "--" << "\r\n"; |
| + file_stream_->WriteSync(ss.str().data(), ss.str().size()); |
| +} |
| + |
| +void WebRtcLogUploadManager::AddPairString(const std::string& key, |
| + const std::string& value) { |
| + // TODO(grunell): Break out the function in cloud print. |
|
Jói
2013/04/26 12:55:10
Yeah, you definitely shouldn't be including stuff
|
| + std::string str; |
| + cloud_print::AddMultipartValueForUpload( |
| + key, value, kMultipartBoundary, "", &str); |
| + file_stream_->WriteSync(str.c_str(), str.size()); |
| +} |
| + |
| +void WebRtcLogUploadManager::AddUrlChunks() { |
| + // TODO(grunell): Implement. |
| +} |
| + |
| +void WebRtcLogUploadManager::AddLogData(uint8* log_data, |
| + uint32 log_data_size) { |
| + std::stringstream ss; |
| + ss << "--" << kMultipartBoundary << "\r\n"; |
| + ss << "Content-Disposition: form-data; name=\"log\""; |
| + ss << "; filename=\"log.bz2\"" << "\r\n"; |
| + ss << "Content-Type: application/x-bzip" << "\r\n"; |
| + ss << "\r\n"; |
| + file_stream_->WriteSync(ss.str().data(), ss.str().size()); |
| + |
| + file_stream_->WriteSync(reinterpret_cast<const char*>(log_data), |
| + log_data_size); |
| + |
| + std::string end_str = "\r\n"; |
| + file_stream_->WriteSync(end_str.c_str(), end_str.size()); |
| +} |