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

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: Rebase 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
« no previous file with comments | « chrome/browser/tracing/crash_service_uploader.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 feedback;
59 string error_message;
60 bool success = (response_code == kHttpResponseOk); 58 bool success = (response_code == kHttpResponseOk);
61 if (success) { 59 if (success) {
62 source->GetResponseAsString(&report_id); 60 source->GetResponseAsString(&feedback);
63 } else { 61 } else {
64 error_message = "Uploading failed, response code: " + 62 feedback =
65 base::IntToString(response_code); 63 "Uploading failed, response code: " + base::IntToString(response_code);
66 } 64 }
67 65
68 BrowserThread::PostTask( 66 content::BrowserThread::PostTask(
69 content::BrowserThread::UI, 67 content::BrowserThread::UI, FROM_HERE,
70 FROM_HERE, 68 base::Bind(done_callback_, success, feedback));
71 base::Bind(done_callback_, success, report_id, error_message));
72 url_fetcher_.reset(); 69 url_fetcher_.reset();
73 } 70 }
74 71
75 void TraceUploader::OnURLFetchUploadProgress( 72 void TraceCrashServiceUploader::OnURLFetchUploadProgress(
76 const net::URLFetcher* source, int64 current, int64 total) { 73 const net::URLFetcher* source,
74 int64 current,
75 int64 total) {
77 DCHECK(url_fetcher_.get()); 76 DCHECK(url_fetcher_.get());
78 77
79 LOG(WARNING) << "Upload progress: " << current << " of " << total; 78 LOG(WARNING) << "Upload progress: " << current << " of " << total;
80 BrowserThread::PostTask( 79 content::BrowserThread::PostTask(
81 content::BrowserThread::UI, 80 content::BrowserThread::UI, FROM_HERE,
82 FROM_HERE,
83 base::Bind(progress_callback_, current, total)); 81 base::Bind(progress_callback_, current, total));
84 } 82 }
85 83
86 void TraceUploader::DoUpload( 84 void TraceCrashServiceUploader::DoUpload(
87 const std::string& file_contents, 85 const std::string& file_contents,
88 UploadProgressCallback progress_callback, 86 const UploadProgressCallback& progress_callback,
89 UploadDoneCallback done_callback) { 87 const UploadDoneCallback& done_callback) {
90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 88 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
89 content::BrowserThread::PostTask(
90 content::BrowserThread::FILE, FROM_HERE,
91 base::Bind(&TraceCrashServiceUploader::DoUploadOnFileThread,
92 base::Unretained(this), file_contents, progress_callback,
93 done_callback));
94 }
95
96 void TraceCrashServiceUploader::DoUploadOnFileThread(
97 const std::string& file_contents,
98 const UploadProgressCallback& progress_callback,
99 const UploadDoneCallback& done_callback) {
100 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
91 DCHECK(!url_fetcher_.get()); 101 DCHECK(!url_fetcher_.get());
92 102
93 progress_callback_ = progress_callback; 103 progress_callback_ = progress_callback;
94 done_callback_ = done_callback; 104 done_callback_ = done_callback;
95 105
106 const base::CommandLine& command_line =
107 *base::CommandLine::ForCurrentProcess();
108 std::string upload_url = kUploadURL;
109 if (command_line.HasSwitch(switches::kTraceUploadURL)) {
110 upload_url = command_line.GetSwitchValueASCII(switches::kTraceUploadURL);
111 }
112 if (!GURL(upload_url).is_valid())
113 upload_url.clear();
114
115 if (upload_url.empty()) {
116 OnUploadError("Upload URL empty or invalid");
117 return;
118 }
119
120 #if defined(OS_WIN)
121 const char product[] = "Chrome";
122 #elif defined(OS_MACOSX)
123 const char product[] = "Chrome_Mac";
124 #elif defined(OS_LINUX)
125 const char product[] = "Chrome_Linux";
126 #elif defined(OS_ANDROID)
127 const char product[] = "Chrome_Android";
128 #elif defined(OS_CHROMEOS)
129 const char product[] = "Chrome_ChromeOS";
130 #else
131 #error Platform not supported.
132 #endif
133
134 // VersionInfo::ProductNameAndVersionForUserAgent() returns a string like
135 // "Chrome/aa.bb.cc.dd", split out the part before the "/".
136 chrome::VersionInfo version_info;
137 std::vector<std::string> product_components;
138 base::SplitString(version_info.ProductNameAndVersionForUserAgent(), '/',
139 &product_components);
140 DCHECK_EQ(2U, product_components.size());
141 std::string version;
142 if (product_components.size() == 2U) {
143 version = product_components[1];
144 } else {
145 version = "unknown";
146 }
147
96 if (url_fetcher_.get()) { 148 if (url_fetcher_.get()) {
97 OnUploadError("Already uploading."); 149 OnUploadError("Already uploading.");
150 return;
98 } 151 }
99 152
100 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]); 153 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]);
101 int compressed_bytes; 154 int compressed_bytes;
102 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(), 155 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(),
103 &compressed_bytes)) { 156 &compressed_bytes)) {
104 OnUploadError("Compressing file failed."); 157 OnUploadError("Compressing file failed.");
105 return; 158 return;
106 } 159 }
107 160
108 std::string post_data; 161 std::string post_data;
109 SetupMultipart("trace.json.gz", 162 SetupMultipart(product, version, "trace.json.gz",
110 std::string(compressed_contents.get(), compressed_bytes), 163 std::string(compressed_contents.get(), compressed_bytes),
111 &post_data); 164 &post_data);
112 165
113 content::BrowserThread::PostTask( 166 content::BrowserThread::PostTask(
114 content::BrowserThread::UI, FROM_HERE, 167 content::BrowserThread::UI, FROM_HERE,
115 base::Bind(&TraceUploader::CreateAndStartURLFetcher, 168 base::Bind(&TraceCrashServiceUploader::CreateAndStartURLFetcher,
116 base::Unretained(this), 169 base::Unretained(this), upload_url, post_data));
117 post_data));
118 } 170 }
119 171
120 void TraceUploader::OnUploadError(std::string error_message) { 172 void TraceCrashServiceUploader::OnUploadError(std::string error_message) {
121 LOG(ERROR) << error_message; 173 LOG(ERROR) << error_message;
122 content::BrowserThread::PostTask( 174 content::BrowserThread::PostTask(
123 content::BrowserThread::UI, 175 content::BrowserThread::UI, FROM_HERE,
124 FROM_HERE, 176 base::Bind(done_callback_, false, error_message));
125 base::Bind(done_callback_, false, "", error_message));
126 } 177 }
127 178
128 void TraceUploader::SetupMultipart(const std::string& trace_filename, 179 void TraceCrashServiceUploader::SetupMultipart(
129 const std::string& trace_contents, 180 const std::string& product,
130 std::string* post_data) { 181 const std::string& version,
131 net::AddMultipartValueForUpload("prod", product_, kMultipartBoundary, "", 182 const std::string& trace_filename,
183 const std::string& trace_contents,
184 std::string* post_data) {
185 net::AddMultipartValueForUpload("prod", product, kMultipartBoundary, "",
132 post_data); 186 post_data);
133 net::AddMultipartValueForUpload("ver", version_ + "-trace", 187 net::AddMultipartValueForUpload("ver", version + "-trace", kMultipartBoundary,
134 kMultipartBoundary, "", post_data);
135 net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary,
136 "", post_data); 188 "", post_data);
137 net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary, 189 net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary, "",
138 "", post_data); 190 post_data);
191 net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary, "",
192 post_data);
139 // No minidump means no need for crash to process the report. 193 // No minidump means no need for crash to process the report.
140 net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary, 194 net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary,
141 "", post_data); 195 "", post_data);
142 196
143 AddTraceFile(trace_filename, trace_contents, post_data); 197 AddTraceFile(trace_filename, trace_contents, post_data);
144 198
145 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); 199 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data);
146 } 200 }
147 201
148 void TraceUploader::AddTraceFile(const std::string& trace_filename, 202 void TraceCrashServiceUploader::AddTraceFile(const std::string& trace_filename,
149 const std::string& trace_contents, 203 const std::string& trace_contents,
150 std::string* post_data) { 204 std::string* post_data) {
151 post_data->append("--"); 205 post_data->append("--");
152 post_data->append(kMultipartBoundary); 206 post_data->append(kMultipartBoundary);
153 post_data->append("\r\n"); 207 post_data->append("\r\n");
154 post_data->append("Content-Disposition: form-data; name=\"trace\""); 208 post_data->append("Content-Disposition: form-data; name=\"trace\"");
155 post_data->append("; filename=\""); 209 post_data->append("; filename=\"");
156 post_data->append(trace_filename); 210 post_data->append(trace_filename);
157 post_data->append("\"\r\n"); 211 post_data->append("\"\r\n");
158 post_data->append("Content-Type: application/gzip\r\n\r\n"); 212 post_data->append("Content-Type: application/gzip\r\n\r\n");
159 post_data->append(trace_contents); 213 post_data->append(trace_contents);
160 post_data->append("\r\n"); 214 post_data->append("\r\n");
161 } 215 }
162 216
163 bool TraceUploader::Compress(std::string input, 217 bool TraceCrashServiceUploader::Compress(std::string input,
164 int max_compressed_bytes, 218 int max_compressed_bytes,
165 char* compressed, 219 char* compressed,
166 int* compressed_bytes) { 220 int* compressed_bytes) {
167 DCHECK(compressed); 221 DCHECK(compressed);
168 DCHECK(compressed_bytes); 222 DCHECK(compressed_bytes);
169 z_stream stream = {0}; 223 z_stream stream = {0};
170 int result = deflateInit2(&stream, 224 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. 225 // 16 is added to produce a gzip header + trailer.
174 MAX_WBITS + 16, 226 MAX_WBITS + 16,
175 8, // memLevel = 8 is default. 227 8, // memLevel = 8 is default.
176 Z_DEFAULT_STRATEGY); 228 Z_DEFAULT_STRATEGY);
177 DCHECK_EQ(Z_OK, result); 229 DCHECK_EQ(Z_OK, result);
178 stream.next_in = reinterpret_cast<uint8*>(&input[0]); 230 stream.next_in = reinterpret_cast<uint8*>(&input[0]);
179 stream.avail_in = input.size(); 231 stream.avail_in = input.size();
180 stream.next_out = reinterpret_cast<uint8*>(compressed); 232 stream.next_out = reinterpret_cast<uint8*>(compressed);
181 stream.avail_out = max_compressed_bytes; 233 stream.avail_out = max_compressed_bytes;
182 // Do a one-shot compression. This will return Z_STREAM_END only if |output| 234 // Do a one-shot compression. This will return Z_STREAM_END only if |output|
183 // is large enough to hold all compressed data. 235 // is large enough to hold all compressed data.
184 result = deflate(&stream, Z_FINISH); 236 result = deflate(&stream, Z_FINISH);
185 bool success = (result == Z_STREAM_END); 237 bool success = (result == Z_STREAM_END);
186 result = deflateEnd(&stream); 238 result = deflateEnd(&stream);
187 DCHECK(result == Z_OK || result == Z_DATA_ERROR); 239 DCHECK(result == Z_OK || result == Z_DATA_ERROR);
188 240
189 if (success) 241 if (success)
190 *compressed_bytes = max_compressed_bytes - stream.avail_out; 242 *compressed_bytes = max_compressed_bytes - stream.avail_out;
191 243
192 LOG(WARNING) << "input size: " << input.size() 244 LOG(WARNING) << "input size: " << input.size()
193 << ", output size: " << *compressed_bytes; 245 << ", output size: " << *compressed_bytes;
194 return success; 246 return success;
195 } 247 }
196 248
197 void TraceUploader::CreateAndStartURLFetcher(const std::string& post_data) { 249 void TraceCrashServiceUploader::CreateAndStartURLFetcher(
198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 250 const std::string& upload_url,
251 const std::string& post_data) {
252 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
199 DCHECK(!url_fetcher_.get()); 253 DCHECK(!url_fetcher_.get());
200 254
201 std::string content_type = kUploadContentType; 255 std::string content_type = kUploadContentType;
202 content_type.append("; boundary="); 256 content_type.append("; boundary=");
203 content_type.append(kMultipartBoundary); 257 content_type.append(kMultipartBoundary);
204 258
205 url_fetcher_.reset( 259 url_fetcher_.reset(
206 net::URLFetcher::Create(GURL(upload_url_), net::URLFetcher::POST, this)); 260 net::URLFetcher::Create(GURL(upload_url), net::URLFetcher::POST, this));
207 url_fetcher_->SetRequestContext(request_context_); 261 url_fetcher_->SetRequestContext(request_context_);
208 url_fetcher_->SetUploadData(content_type, post_data); 262 url_fetcher_->SetUploadData(content_type, post_data);
209 url_fetcher_->Start(); 263 url_fetcher_->Start();
210 } 264 }
211
212 } // namespace content
OLDNEW
« no previous file with comments | « chrome/browser/tracing/crash_service_uploader.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698