OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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/webrtc_log_upload_manager.h" |
| 6 /* |
| 7 #if defined(USE_SYSTEM_LIBBZ2) |
| 8 #include <bzlib.h> |
| 9 #else |
| 10 #include "third_party/bzip2/bzlib.h" |
| 11 #endif |
| 12 */ |
| 13 //#include "base/bind.h" |
| 14 #include "base/command_line.h" |
| 15 #include "base/logging.h" |
| 16 #include "base/prefs/pref_service.h" |
| 17 #include "chrome/browser/browser_process.h" |
| 18 #include "chrome/common/cloud_print/cloud_print_helpers.h" |
| 19 #include "chrome/common/pref_names.h" |
| 20 //#include "content/common/partial_circular_buffer.h" |
| 21 #include "content/public/browser/browser_thread.h" |
| 22 #include "googleurl/src/gurl.h" |
| 23 //#include "net/base/file_stream.h" |
| 24 #include "net/proxy/proxy_config_service.h" |
| 25 #include "net/url_request/url_fetcher.h" |
| 26 #include "net/url_request/url_request_context_builder.h" |
| 27 |
| 28 namespace { |
| 29 |
| 30 const uint32 kIntermediateCompressionBufferSize = 0.5 * 1024 * 1024; // 0.5 MB |
| 31 |
| 32 const char kTempUploadFile[] = "/tmp/chromium-webrtc-log-upload"; |
| 33 const char kUploadURL[] = "https://clients2.google.com/cr/report"; |
| 34 const char kUploadContentType[] = "multipart/form-data"; |
| 35 const char kMultipartBoundary[] = |
| 36 "----**--yradnuoBgoLtrapitluMklaTelgooG--**----"; |
| 37 |
| 38 const uint32 kFileCopyBufferSize = 128 * 1024; // 128 KB |
| 39 |
| 40 // Config getter that always returns direct settings. |
| 41 class ProxyConfigServiceDirect : public net::ProxyConfigService { |
| 42 public: |
| 43 // ProxyConfigService implementation. |
| 44 virtual void AddObserver(Observer* observer) OVERRIDE {} |
| 45 virtual void RemoveObserver(Observer* observer) OVERRIDE {} |
| 46 virtual ConfigAvailability GetLatestProxyConfig( |
| 47 net::ProxyConfig* config) OVERRIDE { |
| 48 *config = net::ProxyConfig::CreateDirect(); |
| 49 return CONFIG_VALID; |
| 50 } |
| 51 }; |
| 52 |
| 53 } // namespace |
| 54 |
| 55 class WebRtcLogURLRequestContextGetter : |
| 56 public net::URLRequestContextGetter { |
| 57 public: |
| 58 WebRtcLogURLRequestContextGetter() {} |
| 59 |
| 60 // net::URLRequestContextGetter implementation. |
| 61 virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE { |
| 62 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
| 63 |
| 64 if (!url_request_context_) { |
| 65 net::URLRequestContextBuilder builder; |
| 66 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 67 builder.set_proxy_config_service(new ProxyConfigServiceDirect()); |
| 68 #endif |
| 69 url_request_context_.reset(builder.Build()); |
| 70 } |
| 71 CHECK(url_request_context_.get()); |
| 72 |
| 73 return url_request_context_.get(); |
| 74 } |
| 75 |
| 76 virtual scoped_refptr<base::SingleThreadTaskRunner> |
| 77 GetNetworkTaskRunner() const OVERRIDE { |
| 78 return content::BrowserThread::GetMessageLoopProxyForThread( |
| 79 content::BrowserThread::IO); |
| 80 } |
| 81 |
| 82 private: |
| 83 virtual ~WebRtcLogURLRequestContextGetter() {} |
| 84 |
| 85 // NULL if not yet initialized. Otherwise, it is the URLRequestContext |
| 86 // instance that was lazily created by GetURLRequestContext(). |
| 87 // Access only from the IO thread. |
| 88 scoped_ptr<net::URLRequestContext> url_request_context_; |
| 89 |
| 90 DISALLOW_COPY_AND_ASSIGN(WebRtcLogURLRequestContextGetter); |
| 91 }; |
| 92 |
| 93 |
| 94 WebRtcLogUploadManager::WebRtcLogUploadManager() |
| 95 : multipart_file_(base::kInvalidPlatformFileValue) { |
| 96 } |
| 97 |
| 98 WebRtcLogUploadManager::~WebRtcLogUploadManager() { |
| 99 } |
| 100 |
| 101 void WebRtcLogUploadManager::OnURLFetchComplete( |
| 102 const net::URLFetcher* source) { |
| 103 std::vector<net::URLFetcher*>::iterator it; |
| 104 for (it = url_fetchers_.begin(); it != url_fetchers_.end(); ++it) { |
| 105 if (*it == source) { |
| 106 url_fetchers_.erase(it); |
| 107 break; |
| 108 } |
| 109 } |
| 110 delete source; |
| 111 } |
| 112 |
| 113 void WebRtcLogUploadManager::OnURLFetchUploadProgress( |
| 114 const net::URLFetcher* source, int64 current, int64 total) { |
| 115 } |
| 116 |
| 117 void WebRtcLogUploadManager::UploadLog(base::PlatformFile log_file) { |
| 118 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
| 119 /* |
| 120 DCHECK(shared_memory); |
| 121 DCHECK(shared_memory->memory()); |
| 122 |
| 123 scoped_ptr<base::SharedMemory> scoped_shared_memory(shared_memory); |
| 124 |
| 125 uint8 compressed[length]; |
| 126 uint32 compressed_size = sizeof(compressed); //content::kWebRtcLogSize; |
| 127 ReadAndCompressLog(reinterpret_cast<uint8*>(scoped_shared_memory->memory()), |
| 128 length, compressed, &compressed_size); |
| 129 */ |
| 130 SetupUpload(log_file); |
| 131 |
| 132 if (!request_context_getter_) |
| 133 request_context_getter_ = new WebRtcLogURLRequestContextGetter(); |
| 134 |
| 135 std::string content_type = kUploadContentType; |
| 136 content_type.append("; boundary="); |
| 137 content_type.append(kMultipartBoundary); |
| 138 |
| 139 net::URLFetcher* url_fetcher = |
| 140 net::URLFetcher::Create(GURL(kUploadURL), net::URLFetcher::POST, this); |
| 141 url_fetcher->SetRequestContext(request_context_getter_); |
| 142 url_fetcher->SetUploadFilePath( |
| 143 content_type, base::FilePath(kTempUploadFile), |
| 144 content::BrowserThread::GetMessageLoopProxyForThread( |
| 145 content::BrowserThread::FILE)); |
| 146 url_fetcher->Start(); |
| 147 url_fetchers_.push_back(url_fetcher); |
| 148 } |
| 149 |
| 150 /* |
| 151 void WebRtcLogUploadManager::ReadAndCompressLog(uint8* input, |
| 152 uint32 input_size, |
| 153 uint8* output, |
| 154 uint32* output_size) { |
| 155 content::PartialCircularBuffer read_pcb(input, input_size); |
| 156 |
| 157 bz_stream stream = {0}; |
| 158 int result = BZ2_bzCompressInit(&stream, 6, 0, 0); |
| 159 DCHECK(result == BZ_OK); |
| 160 |
| 161 scoped_ptr<uint8[]> intermediate_buffer( |
| 162 new uint8[kIntermediateCompressionBufferSize]); |
| 163 memset(intermediate_buffer.get(), 0, kIntermediateCompressionBufferSize); |
| 164 uint32 read = read_pcb.Read(intermediate_buffer.get(), |
| 165 kIntermediateCompressionBufferSize); |
| 166 stream.next_in = reinterpret_cast<char*>(&intermediate_buffer.get()[0]); |
| 167 stream.avail_in = read; |
| 168 |
| 169 while (read == kIntermediateCompressionBufferSize) { |
| 170 stream.next_out = |
| 171 reinterpret_cast<char*>(&((output)[stream.total_out_lo32])); |
| 172 stream.avail_out = *output_size - stream.total_out_lo32; |
| 173 result = BZ2_bzCompress(&stream, BZ_RUN); |
| 174 DCHECK(result == BZ_OK); |
| 175 read = read_pcb.Read(intermediate_buffer.get(), |
| 176 kIntermediateCompressionBufferSize); |
| 177 } |
| 178 |
| 179 stream.avail_in = read; |
| 180 do { |
| 181 stream.next_out = |
| 182 reinterpret_cast<char*>(&((output)[stream.total_out_lo32])); |
| 183 stream.avail_out = *output_size - stream.total_out_lo32; |
| 184 result = BZ2_bzCompress(&stream, BZ_FINISH); |
| 185 } while (result == BZ_FINISH_OK); |
| 186 DCHECK(result == BZ_STREAM_END); |
| 187 |
| 188 result = BZ2_bzCompressEnd(&stream); |
| 189 DCHECK(result == BZ_OK); |
| 190 |
| 191 *output_size = stream.total_out_lo32; |
| 192 } |
| 193 */ |
| 194 |
| 195 void WebRtcLogUploadManager::SetupUpload(base::PlatformFile log_file) { |
| 196 /* |
| 197 file_stream_.reset(new net::FileStream(NULL)); |
| 198 int open_flags = base::PLATFORM_FILE_CREATE_ALWAYS | |
| 199 base::PLATFORM_FILE_WRITE; |
| 200 file_stream_->OpenSync(base::FilePath(kTempUploadFile), |
| 201 open_flags); |
| 202 */ |
| 203 |
| 204 int flags = base::PLATFORM_FILE_CREATE_ALWAYS | |
| 205 base::PLATFORM_FILE_WRITE /*| |
| 206 base::PLATFORM_FILE_DELETE_ON_CLOSE*/; |
| 207 bool created = false; |
| 208 base::PlatformFileError error = base::PLATFORM_FILE_OK; |
| 209 multipart_file_ = |
| 210 CreatePlatformFile(base::FilePath(kTempUploadFile), flags, |
| 211 &created, &error); |
| 212 DCHECK(created); |
| 213 DCHECK(error == base::PLATFORM_FILE_OK); |
| 214 |
| 215 // TODO(grunell): Correct product name. |
| 216 AddPairString("prod", "Chrome"); |
| 217 // TODO(grunell): Correct version. |
| 218 AddPairString("ver", "0.0.1.1-dev-test"); |
| 219 AddPairString("type", "log"); |
| 220 |
| 221 AddUrlChunks(); |
| 222 |
| 223 AddLogData(log_file); |
| 224 |
| 225 std::stringstream ss; |
| 226 ss << "--" << kMultipartBoundary << "--" << "\r\n"; |
| 227 base::WritePlatformFileAtCurrentPos( |
| 228 multipart_file_, ss.str().data(), ss.str().size()); |
| 229 |
| 230 // TODO(grunell): Close file? |
| 231 } |
| 232 |
| 233 void WebRtcLogUploadManager::AddPairString(const std::string& key, |
| 234 const std::string& value) { |
| 235 // TODO(grunell): Break out the function in cloud print. |
| 236 std::string str; |
| 237 cloud_print::AddMultipartValueForUpload( |
| 238 key, value, kMultipartBoundary, "", &str); |
| 239 // file_stream_->WriteSync(str.c_str(), str.size()); |
| 240 base::WritePlatformFileAtCurrentPos(multipart_file_, str.c_str(), str.size()); |
| 241 } |
| 242 |
| 243 void WebRtcLogUploadManager::AddUrlChunks() { |
| 244 // TODO(grunell): Implement. |
| 245 } |
| 246 |
| 247 void WebRtcLogUploadManager::AddLogData(base::PlatformFile log_file) { |
| 248 std::stringstream ss; |
| 249 ss << "--" << kMultipartBoundary << "\r\n"; |
| 250 ss << "Content-Disposition: form-data; name=\"log\""; |
| 251 ss << "; filename=\"log.bz2\"" << "\r\n"; |
| 252 ss << "Content-Type: application/x-bzip" << "\r\n"; |
| 253 ss << "\r\n"; |
| 254 // file_stream_->WriteSync(ss.str().data(), ss.str().size()); |
| 255 base::WritePlatformFileAtCurrentPos( |
| 256 multipart_file_, ss.str().data(), ss.str().size()); |
| 257 |
| 258 // file_stream_->WriteSync(reinterpret_cast<const char*>(log_data), |
| 259 // log_data_size); |
| 260 // Copy the log file contents |
| 261 char buffer[kFileCopyBufferSize] = {0}; |
| 262 int read = 0; |
| 263 int written = 0; |
| 264 int acc_written = 0; |
| 265 do { |
| 266 read = base::ReadPlatformFileAtCurrentPos(log_file, &buffer[0], |
| 267 sizeof(buffer)); |
| 268 DCHECK_GE(read, 0); |
| 269 written = base::WritePlatformFileAtCurrentPos(multipart_file_, &buffer[0], |
| 270 read); |
| 271 DCHECK_GE(written, 0); |
| 272 DCHECK_EQ(read, written); |
| 273 acc_written += written; |
| 274 } while (read > 0); |
| 275 |
| 276 LOG(ERROR) << "TOTAL WRITTEN = " << acc_written; |
| 277 |
| 278 std::string end_str = "\r\n"; |
| 279 // file_stream_->WriteSync(end_str.c_str(), end_str.size()); |
| 280 base::WritePlatformFileAtCurrentPos( |
| 281 multipart_file_, end_str.c_str(), end_str.size()); |
| 282 } |
OLD | NEW |