| OLD | NEW |
| 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 "chrome/browser/tracing/crash_service_uploader.h" | 5 #include "chrome/browser/tracing/crash_service_uploader.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 net::URLRequestContextGetter* request_context) | 43 net::URLRequestContextGetter* request_context) |
| 44 : request_context_(request_context) { | 44 : request_context_(request_context) { |
| 45 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 45 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 46 const base::CommandLine& command_line = | 46 const base::CommandLine& command_line = |
| 47 *base::CommandLine::ForCurrentProcess(); | 47 *base::CommandLine::ForCurrentProcess(); |
| 48 std::string upload_url = kUploadURL; | 48 std::string upload_url = kUploadURL; |
| 49 if (command_line.HasSwitch(switches::kTraceUploadURL)) { | 49 if (command_line.HasSwitch(switches::kTraceUploadURL)) { |
| 50 upload_url = command_line.GetSwitchValueASCII(switches::kTraceUploadURL); | 50 upload_url = command_line.GetSwitchValueASCII(switches::kTraceUploadURL); |
| 51 } | 51 } |
| 52 SetUploadURL(upload_url); | 52 SetUploadURL(upload_url); |
| 53 |
| 54 #if defined(OS_WIN) |
| 55 const char product[] = "Chrome"; |
| 56 #elif defined(OS_MACOSX) |
| 57 const char product[] = "Chrome_Mac"; |
| 58 #elif defined(OS_LINUX) |
| 59 const char product[] = "Chrome_Linux"; |
| 60 #elif defined(OS_ANDROID) |
| 61 const char product[] = "Chrome_Android"; |
| 62 #elif defined(OS_CHROMEOS) |
| 63 const char product[] = "Chrome_ChromeOS"; |
| 64 #else |
| 65 #error Platform not supported. |
| 66 #endif |
| 67 |
| 68 // VersionInfo::ProductNameAndVersionForUserAgent() returns a string like |
| 69 // "Chrome/aa.bb.cc.dd", split out the part before the "/". |
| 70 chrome::VersionInfo version_info; |
| 71 std::vector<std::string> product_components; |
| 72 base::SplitString(version_info.ProductNameAndVersionForUserAgent(), '/', |
| 73 &product_components); |
| 74 DCHECK_EQ(2U, product_components.size()); |
| 75 std::string version; |
| 76 if (product_components.size() == 2U) { |
| 77 version = product_components[1]; |
| 78 } else { |
| 79 version = "unknown"; |
| 80 } |
| 81 |
| 82 metadata_.insert(std::pair<std::string, std::string>("prod", product)); |
| 83 metadata_.insert( |
| 84 std::pair<std::string, std::string>("ver", version + "-trace")); |
| 85 metadata_.insert(std::pair<std::string, std::string>("guid", "0")); |
| 86 metadata_.insert(std::pair<std::string, std::string>("type", "trace")); |
| 87 // No minidump means no need for crash to process the report. |
| 88 metadata_.insert( |
| 89 std::pair<std::string, std::string>("should_process", "false")); |
| 53 } | 90 } |
| 54 | 91 |
| 55 TraceCrashServiceUploader::~TraceCrashServiceUploader() { | 92 TraceCrashServiceUploader::~TraceCrashServiceUploader() { |
| 56 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 93 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 57 } | 94 } |
| 58 | 95 |
| 59 void TraceCrashServiceUploader::SetUploadURL(const std::string& url) { | 96 void TraceCrashServiceUploader::SetUploadURL(const std::string& url) { |
| 60 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 97 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 61 upload_url_ = url; | 98 upload_url_ = url; |
| 62 | 99 |
| 63 if (!GURL(upload_url_).is_valid()) | 100 if (!GURL(upload_url_).is_valid()) |
| 64 upload_url_.clear(); | 101 upload_url_.clear(); |
| 65 } | 102 } |
| 66 | 103 |
| 104 void TraceCrashServiceUploader::SetMetadata( |
| 105 const std::map<std::string, std::string>& metadata) { |
| 106 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 107 metadata_.insert(metadata.begin(), metadata.end()); |
| 108 } |
| 109 |
| 67 void TraceCrashServiceUploader::OnURLFetchComplete( | 110 void TraceCrashServiceUploader::OnURLFetchComplete( |
| 68 const net::URLFetcher* source) { | 111 const net::URLFetcher* source) { |
| 69 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 70 DCHECK_EQ(source, url_fetcher_.get()); | 113 DCHECK_EQ(source, url_fetcher_.get()); |
| 71 int response_code = source->GetResponseCode(); | 114 int response_code = source->GetResponseCode(); |
| 72 string feedback; | 115 string feedback; |
| 73 bool success = (response_code == kHttpResponseOk); | 116 bool success = (response_code == kHttpResponseOk); |
| 74 if (success) { | 117 if (success) { |
| 75 source->GetResponseAsString(&feedback); | 118 source->GetResponseAsString(&feedback); |
| 76 } else { | 119 } else { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 97 } | 140 } |
| 98 | 141 |
| 99 void TraceCrashServiceUploader::DoUpload( | 142 void TraceCrashServiceUploader::DoUpload( |
| 100 const std::string& file_contents, | 143 const std::string& file_contents, |
| 101 const UploadProgressCallback& progress_callback, | 144 const UploadProgressCallback& progress_callback, |
| 102 const UploadDoneCallback& done_callback) { | 145 const UploadDoneCallback& done_callback) { |
| 103 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 104 content::BrowserThread::PostTask( | 147 content::BrowserThread::PostTask( |
| 105 content::BrowserThread::FILE, FROM_HERE, | 148 content::BrowserThread::FILE, FROM_HERE, |
| 106 base::Bind(&TraceCrashServiceUploader::DoUploadOnFileThread, | 149 base::Bind(&TraceCrashServiceUploader::DoUploadOnFileThread, |
| 107 base::Unretained(this), file_contents, upload_url_, | 150 base::Unretained(this), file_contents, upload_url_, metadata_, |
| 108 progress_callback, done_callback)); | 151 progress_callback, done_callback)); |
| 109 } | 152 } |
| 110 | 153 |
| 111 void TraceCrashServiceUploader::DoUploadOnFileThread( | 154 void TraceCrashServiceUploader::DoUploadOnFileThread( |
| 112 const std::string& file_contents, | 155 const std::string& file_contents, |
| 113 const std::string& upload_url, | 156 const std::string& upload_url, |
| 157 const std::map<std::string, std::string>& metadata, |
| 114 const UploadProgressCallback& progress_callback, | 158 const UploadProgressCallback& progress_callback, |
| 115 const UploadDoneCallback& done_callback) { | 159 const UploadDoneCallback& done_callback) { |
| 116 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); | 160 DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); |
| 117 DCHECK(!url_fetcher_.get()); | 161 DCHECK(!url_fetcher_.get()); |
| 118 | 162 |
| 119 progress_callback_ = progress_callback; | 163 progress_callback_ = progress_callback; |
| 120 done_callback_ = done_callback; | 164 done_callback_ = done_callback; |
| 121 | 165 |
| 122 if (upload_url.empty()) { | 166 if (upload_url.empty()) { |
| 123 OnUploadError("Upload URL empty or invalid"); | 167 OnUploadError("Upload URL empty or invalid"); |
| 124 return; | 168 return; |
| 125 } | 169 } |
| 126 | 170 |
| 127 #if defined(OS_WIN) | |
| 128 const char product[] = "Chrome"; | |
| 129 #elif defined(OS_MACOSX) | |
| 130 const char product[] = "Chrome_Mac"; | |
| 131 #elif defined(OS_LINUX) | |
| 132 const char product[] = "Chrome_Linux"; | |
| 133 #elif defined(OS_ANDROID) | |
| 134 const char product[] = "Chrome_Android"; | |
| 135 #elif defined(OS_CHROMEOS) | |
| 136 const char product[] = "Chrome_ChromeOS"; | |
| 137 #else | |
| 138 #error Platform not supported. | |
| 139 #endif | |
| 140 | |
| 141 // VersionInfo::ProductNameAndVersionForUserAgent() returns a string like | |
| 142 // "Chrome/aa.bb.cc.dd", split out the part before the "/". | |
| 143 chrome::VersionInfo version_info; | |
| 144 std::vector<std::string> product_components; | |
| 145 base::SplitString(version_info.ProductNameAndVersionForUserAgent(), '/', | |
| 146 &product_components); | |
| 147 DCHECK_EQ(2U, product_components.size()); | |
| 148 std::string version; | |
| 149 if (product_components.size() == 2U) { | |
| 150 version = product_components[1]; | |
| 151 } else { | |
| 152 version = "unknown"; | |
| 153 } | |
| 154 | |
| 155 if (url_fetcher_.get()) { | 171 if (url_fetcher_.get()) { |
| 156 OnUploadError("Already uploading."); | 172 OnUploadError("Already uploading."); |
| 157 return; | 173 return; |
| 158 } | 174 } |
| 159 | 175 |
| 160 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]); | 176 scoped_ptr<char[]> compressed_contents(new char[kMaxUploadBytes]); |
| 161 int compressed_bytes; | 177 int compressed_bytes; |
| 162 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(), | 178 if (!Compress(file_contents, kMaxUploadBytes, compressed_contents.get(), |
| 163 &compressed_bytes)) { | 179 &compressed_bytes)) { |
| 164 OnUploadError("Compressing file failed."); | 180 OnUploadError("Compressing file failed."); |
| 165 return; | 181 return; |
| 166 } | 182 } |
| 167 | 183 |
| 168 std::string post_data; | 184 std::string post_data; |
| 169 SetupMultipart(product, version, "trace.json.gz", | 185 SetupMultipart(metadata, "trace.json.gz", |
| 170 std::string(compressed_contents.get(), compressed_bytes), | 186 std::string(compressed_contents.get(), compressed_bytes), |
| 171 &post_data); | 187 &post_data); |
| 172 | 188 |
| 173 content::BrowserThread::PostTask( | 189 content::BrowserThread::PostTask( |
| 174 content::BrowserThread::UI, FROM_HERE, | 190 content::BrowserThread::UI, FROM_HERE, |
| 175 base::Bind(&TraceCrashServiceUploader::CreateAndStartURLFetcher, | 191 base::Bind(&TraceCrashServiceUploader::CreateAndStartURLFetcher, |
| 176 base::Unretained(this), upload_url, post_data)); | 192 base::Unretained(this), upload_url, post_data)); |
| 177 } | 193 } |
| 178 | 194 |
| 179 void TraceCrashServiceUploader::OnUploadError(std::string error_message) { | 195 void TraceCrashServiceUploader::OnUploadError(std::string error_message) { |
| 180 LOG(ERROR) << error_message; | 196 LOG(ERROR) << error_message; |
| 181 content::BrowserThread::PostTask( | 197 content::BrowserThread::PostTask( |
| 182 content::BrowserThread::UI, FROM_HERE, | 198 content::BrowserThread::UI, FROM_HERE, |
| 183 base::Bind(done_callback_, false, error_message)); | 199 base::Bind(done_callback_, false, error_message)); |
| 184 } | 200 } |
| 185 | 201 |
| 186 void TraceCrashServiceUploader::SetupMultipart( | 202 void TraceCrashServiceUploader::SetupMultipart( |
| 187 const std::string& product, | 203 const std::map<std::string, std::string>& metadata, |
| 188 const std::string& version, | |
| 189 const std::string& trace_filename, | 204 const std::string& trace_filename, |
| 190 const std::string& trace_contents, | 205 const std::string& trace_contents, |
| 191 std::string* post_data) { | 206 std::string* post_data) { |
| 192 net::AddMultipartValueForUpload("prod", product, kMultipartBoundary, "", | 207 for (auto it = metadata.begin(); it != metadata.end(); ++it) { |
| 193 post_data); | 208 net::AddMultipartValueForUpload(it->first, it->second, kMultipartBoundary, |
| 194 net::AddMultipartValueForUpload("ver", version + "-trace", kMultipartBoundary, | 209 "", post_data); |
| 195 "", post_data); | 210 } |
| 196 net::AddMultipartValueForUpload("guid", "0", kMultipartBoundary, "", | |
| 197 post_data); | |
| 198 net::AddMultipartValueForUpload("type", "trace", kMultipartBoundary, "", | |
| 199 post_data); | |
| 200 // No minidump means no need for crash to process the report. | |
| 201 net::AddMultipartValueForUpload("should_process", "false", kMultipartBoundary, | |
| 202 "", post_data); | |
| 203 | 211 |
| 204 AddTraceFile(trace_filename, trace_contents, post_data); | 212 AddTraceFile(trace_filename, trace_contents, post_data); |
| 205 | 213 |
| 206 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); | 214 net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data); |
| 207 } | 215 } |
| 208 | 216 |
| 209 void TraceCrashServiceUploader::AddTraceFile(const std::string& trace_filename, | 217 void TraceCrashServiceUploader::AddTraceFile(const std::string& trace_filename, |
| 210 const std::string& trace_contents, | 218 const std::string& trace_contents, |
| 211 std::string* post_data) { | 219 std::string* post_data) { |
| 212 post_data->append("--"); | 220 post_data->append("--"); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 std::string content_type = kUploadContentType; | 270 std::string content_type = kUploadContentType; |
| 263 content_type.append("; boundary="); | 271 content_type.append("; boundary="); |
| 264 content_type.append(kMultipartBoundary); | 272 content_type.append(kMultipartBoundary); |
| 265 | 273 |
| 266 url_fetcher_ = | 274 url_fetcher_ = |
| 267 net::URLFetcher::Create(GURL(upload_url), net::URLFetcher::POST, this); | 275 net::URLFetcher::Create(GURL(upload_url), net::URLFetcher::POST, this); |
| 268 url_fetcher_->SetRequestContext(request_context_); | 276 url_fetcher_->SetRequestContext(request_context_); |
| 269 url_fetcher_->SetUploadData(content_type, post_data); | 277 url_fetcher_->SetUploadData(content_type, post_data); |
| 270 url_fetcher_->Start(); | 278 url_fetcher_->Start(); |
| 271 } | 279 } |
| OLD | NEW |