Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/tracing/crash_service_uploader.cc

Issue 911153002: Moved the TraceUploader to chrome/ and abstracted it for alternative new upload destinations. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix TraceUploader ownership Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/tracing/trace_uploader.h" 5 #include "chrome/browser/tracing/crash_service_uploader.h"
6 6
7 #include "base/command_line.h"
7 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
8 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/format_macros.h"
9 #include "base/memory/shared_memory.h" 11 #include "base/memory/shared_memory.h"
10 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
12 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "chrome/common/chrome_version_info.h"
13 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/common/content_switches.h"
14 #include "net/base/mime_util.h" 20 #include "net/base/mime_util.h"
15 #include "net/base/network_delegate.h" 21 #include "net/base/network_delegate.h"
16 #include "net/proxy/proxy_config.h" 22 #include "net/proxy/proxy_config.h"
17 #include "net/proxy/proxy_config_service.h" 23 #include "net/proxy/proxy_config_service.h"
18 #include "net/url_request/url_fetcher.h" 24 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_request_context.h" 25 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_context_builder.h" 26 #include "net/url_request/url_request_context_builder.h"
21 #include "net/url_request/url_request_context_getter.h" 27 #include "net/url_request/url_request_context_getter.h"
22 #include "third_party/zlib/zlib.h" 28 #include "third_party/zlib/zlib.h"
23 #include "url/gurl.h" 29 #include "url/gurl.h"
24 30
25 using std::string; 31 using std::string;
26 32
27 namespace content {
28 namespace { 33 namespace {
34 const char kUploadURL[] = "https://clients2.google.com/cr/staging_report";
29 const char kUploadContentType[] = "multipart/form-data"; 35 const char kUploadContentType[] = "multipart/form-data";
30 const char kMultipartBoundary[] = 36 const char kMultipartBoundary[] =
31 "----**--yradnuoBgoLtrapitluMklaTelgooG--**----"; 37 "----**--yradnuoBgoLtrapitluMklaTelgooG--**----";
32
33 const int kHttpResponseOk = 200; 38 const int kHttpResponseOk = 200;
34 39
35 } // namespace 40 } // namespace
36 41
37 TraceUploader::TraceUploader(const std::string& product, 42 TraceCrashServiceUploader::TraceCrashServiceUploader(
38 const std::string& version, 43 net::URLRequestContextGetter* request_context)
39 const std::string& upload_url, 44 : request_context_(request_context) {
40 net::URLRequestContextGetter* request_context) 45 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
41 : product_(product),
42 version_(version),
43 upload_url_(upload_url),
44 request_context_(request_context) {
45 DCHECK(!product_.empty());
46 DCHECK(!version_.empty());
47 DCHECK(!upload_url_.empty());
48 } 46 }
49 47
50 TraceUploader::~TraceUploader() { 48 TraceCrashServiceUploader::~TraceCrashServiceUploader() {
51 DCHECK_CURRENTLY_ON(BrowserThread::UI); 49 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
52 } 50 }
53 51
54 void TraceUploader::OnURLFetchComplete(const net::URLFetcher* source) { 52 void TraceCrashServiceUploader::OnURLFetchComplete(
55 DCHECK_CURRENTLY_ON(BrowserThread::UI); 53 const net::URLFetcher* source) {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
56 DCHECK_EQ(source, url_fetcher_.get()); 55 DCHECK_EQ(source, url_fetcher_.get());
57 int response_code = source->GetResponseCode(); 56 int response_code = source->GetResponseCode();
58 string report_id; 57 string report_id;
59 string error_message; 58 string error_message;
60 bool success = (response_code == kHttpResponseOk); 59 bool success = (response_code == kHttpResponseOk);
61 if (success) { 60 if (success) {
62 source->GetResponseAsString(&report_id); 61 source->GetResponseAsString(&report_id);
63 } else { 62 } else {
64 error_message = "Uploading failed, response code: " + 63 error_message =
65 base::IntToString(response_code); 64 "Uploading failed, response code: " + base::IntToString(response_code);
66 } 65 }
67 66
68 BrowserThread::PostTask( 67 content::BrowserThread::PostTask(
69 content::BrowserThread::UI, 68 content::BrowserThread::UI, FROM_HERE,
dsinclair 2015/02/12 20:57:35 nit: This looks short enough to fit on one line?
oystein (OOO til 10th of July) 2015/02/13 17:02:45 The two first arguments yes, but the base::Bind()
70 FROM_HERE,
71 base::Bind(done_callback_, success, report_id, error_message)); 69 base::Bind(done_callback_, success, report_id, error_message));
72 url_fetcher_.reset(); 70 url_fetcher_.reset();
73 } 71 }
74 72
75 void TraceUploader::OnURLFetchUploadProgress( 73 void TraceCrashServiceUploader::OnURLFetchUploadProgress(
76 const net::URLFetcher* source, int64 current, int64 total) { 74 const net::URLFetcher* source,
75 int64 current,
76 int64 total) {
77 DCHECK(url_fetcher_.get()); 77 DCHECK(url_fetcher_.get());
78 78
79 LOG(WARNING) << "Upload progress: " << current << " of " << total; 79 LOG(WARNING) << "Upload progress: " << current << " of " << total;
80 BrowserThread::PostTask( 80 content::BrowserThread::PostTask(
81 content::BrowserThread::UI, 81 content::BrowserThread::UI, FROM_HERE,
82 FROM_HERE,
83 base::Bind(progress_callback_, current, total)); 82 base::Bind(progress_callback_, current, total));
84 } 83 }
85 84
86 void TraceUploader::DoUpload( 85 void TraceCrashServiceUploader::DoUpload(
87 const std::string& file_contents, 86 const std::string& file_contents,
88 UploadProgressCallback progress_callback, 87 const UploadProgressCallback& progress_callback,
89 UploadDoneCallback done_callback) { 88 const UploadDoneCallback& done_callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 89 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
90 content::BrowserThread::PostTask(
91 content::BrowserThread::FILE, FROM_HERE,
92 base::Bind(&TraceCrashServiceUploader::DoUploadOnFileThread,
93 base::Unretained(this), file_contents, progress_callback,
94 done_callback));
95 }
96
97 void TraceCrashServiceUploader::DoUploadOnFileThread(
98 const std::string& file_contents,
99 const UploadProgressCallback& progress_callback,
100 const UploadDoneCallback& done_callback) {
101 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
91 DCHECK(!url_fetcher_.get()); 102 DCHECK(!url_fetcher_.get());
92 103
93 progress_callback_ = progress_callback; 104 progress_callback_ = progress_callback;
94 done_callback_ = done_callback; 105 done_callback_ = done_callback;
95 106
107 const base::CommandLine& command_line =
108 *base::CommandLine::ForCurrentProcess();
109 std::string upload_url = kUploadURL;
110 if (command_line.HasSwitch(switches::kTraceUploadURL)) {
111 upload_url = command_line.GetSwitchValueASCII(switches::kTraceUploadURL);
112 }
113 if (!GURL(upload_url).is_valid()) {
dsinclair 2015/02/12 20:57:35 nit: Don't need {} on single line statement.
oystein (OOO til 10th of July) 2015/02/13 17:02:45 Done.
114 upload_url.clear();
115 }
116
117 if (upload_url.empty()) {
118 OnUploadError("Upload URL empty or invalid");
119 return;
120 }
121
122 #if defined(OS_WIN)
123 const char product[] = "Chrome";
124 #elif defined(OS_MACOSX)
125 const char product[] = "Chrome_Mac";
126 #elif defined(OS_LINUX)
127 const char product[] = "Chrome_Linux";
128 #elif defined(OS_ANDROID)
129 const char product[] = "Chrome_Android";
130 #elif defined(OS_CHROMEOS)
131 const char product[] = "Chrome_ChromeOS";
132 #else
133 #error Platform not supported.
134 #endif
135
136 // VersionInfo::ProductNameAndVersionForUserAgent() returns a string like
137 // "Chrome/aa.bb.cc.dd", split out the part before the "/".
138 chrome::VersionInfo version_info;
139 std::vector<std::string> product_components;
140 base::SplitString(version_info.ProductNameAndVersionForUserAgent(), '/',
141 &product_components);
142 DCHECK_EQ(2U, product_components.size());
143 std::string version;
144 if (product_components.size() == 2U) {
145 version = product_components[1];
146 } else {
147 version = "unknown";
148 }
149
96 if (url_fetcher_.get()) { 150 if (url_fetcher_.get()) {
97 OnUploadError("Already uploading."); 151 OnUploadError("Already uploading.");
152 return;
98 } 153 }
99 154
100 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]); 155 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]);
101 int compressed_bytes; 156 int compressed_bytes;
102 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(), 157 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(),
103 &compressed_bytes)) { 158 &compressed_bytes)) {
104 OnUploadError("Compressing file failed."); 159 OnUploadError("Compressing file failed.");
105 return; 160 return;
106 } 161 }
107 162
108 std::string post_data; 163 std::string post_data;
109 SetupMultipart("trace.json.gz", 164 SetupMultipart(product, version, "trace.json.gz",
110 std::string(compressed_contents.get(), compressed_bytes), 165 std::string(compressed_contents.get(), compressed_bytes),
111 &post_data); 166 &post_data);
112 167
113 content::BrowserThread::PostTask( 168 content::BrowserThread::PostTask(
114 content::BrowserThread::UI, FROM_HERE, 169 content::BrowserThread::UI, FROM_HERE,
115 base::Bind(&TraceUploader::CreateAndStartURLFetcher, 170 base::Bind(&TraceCrashServiceUploader::CreateAndStartURLFetcher,
116 base::Unretained(this), 171 base::Unretained(this), upload_url, post_data));
117 post_data));
118 } 172 }
119 173
120 void TraceUploader::OnUploadError(std::string error_message) { 174 void TraceCrashServiceUploader::OnUploadError(std::string error_message) {
121 LOG(ERROR) << error_message; 175 LOG(ERROR) << error_message;
122 content::BrowserThread::PostTask( 176 content::BrowserThread::PostTask(
123 content::BrowserThread::UI, 177 content::BrowserThread::UI, FROM_HERE,
124 FROM_HERE,
125 base::Bind(done_callback_, false, "", error_message)); 178 base::Bind(done_callback_, false, "", error_message));
126 } 179 }
127 180
128 void TraceUploader::SetupMultipart(const std::string& trace_filename, 181 void TraceCrashServiceUploader::SetupMultipart(
129 const std::string& trace_contents, 182 const std::string& product,
130 std::string* post_data) { 183 const std::string& version,
131 net::AddMultipartValueForUpload("prod", product_, kMultipartBoundary, "", 184 const std::string& trace_filename,
185 const std::string& trace_contents,
186 std::string* post_data) {
187 net::AddMultipartValueForUpload("prod", product, kMultipartBoundary, "",
132 post_data); 188 post_data);
133 net::AddMultipartValueForUpload("ver", version_ + "-trace", 189 net::AddMultipartValueForUpload("ver", version + "-trace", kMultipartBoundary,
134 kMultipartBoundary, "", post_data);
135 net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary,
136 "", post_data); 190 "", post_data);
137 net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary, 191 net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary, "",
138 "", post_data); 192 post_data);
193 net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary, "",
194 post_data);
139 // No minidump means no need for crash to process the report. 195 // No minidump means no need for crash to process the report.
140 net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary, 196 net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary,
141 "", post_data); 197 "", post_data);
142 198
143 AddTraceFile(trace_filename, trace_contents, post_data); 199 AddTraceFile(trace_filename, trace_contents, post_data);
144 200
145 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); 201 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data);
146 } 202 }
147 203
148 void TraceUploader::AddTraceFile(const std::string& trace_filename, 204 void TraceCrashServiceUploader::AddTraceFile(const std::string& trace_filename,
149 const std::string& trace_contents, 205 const std::string& trace_contents,
150 std::string* post_data) { 206 std::string* post_data) {
151 post_data->append("--"); 207 post_data->append("--");
152 post_data->append(kMultipartBoundary); 208 post_data->append(kMultipartBoundary);
153 post_data->append("\r\n"); 209 post_data->append("\r\n");
154 post_data->append("Content-Disposition: form-data; name=\"trace\""); 210 post_data->append("Content-Disposition: form-data; name=\"trace\"");
155 post_data->append("; filename=\""); 211 post_data->append("; filename=\"");
156 post_data->append(trace_filename); 212 post_data->append(trace_filename);
157 post_data->append("\"\r\n"); 213 post_data->append("\"\r\n");
158 post_data->append("Content-Type: application/gzip\r\n\r\n"); 214 post_data->append("Content-Type: application/gzip\r\n\r\n");
159 post_data->append(trace_contents); 215 post_data->append(trace_contents);
160 post_data->append("\r\n"); 216 post_data->append("\r\n");
161 } 217 }
162 218
163 bool TraceUploader::Compress(std::string input, 219 bool TraceCrashServiceUploader::Compress(std::string input,
164 int max_compressed_bytes, 220 int max_compressed_bytes,
165 char* compressed, 221 char* compressed,
166 int* compressed_bytes) { 222 int* compressed_bytes) {
167 DCHECK(compressed); 223 DCHECK(compressed);
168 DCHECK(compressed_bytes); 224 DCHECK(compressed_bytes);
169 z_stream stream = {0}; 225 z_stream stream = {0};
170 int result = deflateInit2(&stream, 226 int result = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
171 Z_DEFAULT_COMPRESSION,
172 Z_DEFLATED,
173 // 16 is added to produce a gzip header + trailer. 227 // 16 is added to produce a gzip header + trailer.
174 MAX_WBITS + 16, 228 MAX_WBITS + 16,
175 8, // memLevel = 8 is default. 229 8, // memLevel = 8 is default.
176 Z_DEFAULT_STRATEGY); 230 Z_DEFAULT_STRATEGY);
177 DCHECK_EQ(Z_OK, result); 231 DCHECK_EQ(Z_OK, result);
178 stream.next_in = reinterpret_cast<uint8*>(&input[0]); 232 stream.next_in = reinterpret_cast<uint8*>(&input[0]);
179 stream.avail_in = input.size(); 233 stream.avail_in = input.size();
180 stream.next_out = reinterpret_cast<uint8*>(compressed); 234 stream.next_out = reinterpret_cast<uint8*>(compressed);
181 stream.avail_out = max_compressed_bytes; 235 stream.avail_out = max_compressed_bytes;
182 // Do a one-shot compression. This will return Z_STREAM_END only if |output| 236 // Do a one-shot compression. This will return Z_STREAM_END only if |output|
183 // is large enough to hold all compressed data. 237 // is large enough to hold all compressed data.
184 result = deflate(&stream, Z_FINISH); 238 result = deflate(&stream, Z_FINISH);
185 bool success = (result == Z_STREAM_END); 239 bool success = (result == Z_STREAM_END);
186 result = deflateEnd(&stream); 240 result = deflateEnd(&stream);
187 DCHECK(result == Z_OK || result == Z_DATA_ERROR); 241 DCHECK(result == Z_OK || result == Z_DATA_ERROR);
188 242
189 if (success) 243 if (success)
190 *compressed_bytes = max_compressed_bytes - stream.avail_out; 244 *compressed_bytes = max_compressed_bytes - stream.avail_out;
191 245
192 LOG(WARNING) << "input size: " << input.size() 246 LOG(WARNING) << "input size: " << input.size()
193 << ", output size: " << *compressed_bytes; 247 << ", output size: " << *compressed_bytes;
194 return success; 248 return success;
195 } 249 }
196 250
197 void TraceUploader::CreateAndStartURLFetcher(const std::string& post_data) { 251 void TraceCrashServiceUploader::CreateAndStartURLFetcher(
198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 252 const std::string& upload_url,
253 const std::string& post_data) {
254 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
199 DCHECK(!url_fetcher_.get()); 255 DCHECK(!url_fetcher_.get());
200 256
201 std::string content_type = kUploadContentType; 257 std::string content_type = kUploadContentType;
202 content_type.append("; boundary="); 258 content_type.append("; boundary=");
203 content_type.append(kMultipartBoundary); 259 content_type.append(kMultipartBoundary);
204 260
205 url_fetcher_.reset( 261 url_fetcher_.reset(
206 net::URLFetcher::Create(GURL(upload_url_), net::URLFetcher::POST, this)); 262 net::URLFetcher::Create(GURL(upload_url), net::URLFetcher::POST, this));
207 url_fetcher_->SetRequestContext(request_context_); 263 url_fetcher_->SetRequestContext(request_context_);
208 url_fetcher_->SetUploadData(content_type, post_data); 264 url_fetcher_->SetUploadData(content_type, post_data);
209 url_fetcher_->Start(); 265 url_fetcher_->Start();
210 } 266 }
211
212 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698