| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 5 |
| 6 //------------------------------------------------------------------------------ | 6 //------------------------------------------------------------------------------ |
| 7 // Description of the life cycle of a instance of MetricsService. | 7 // Description of the life cycle of a instance of MetricsService. |
| 8 // | 8 // |
| 9 // OVERVIEW | 9 // OVERVIEW |
| 10 // | 10 // |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 #include <windows.h> | 45 #include <windows.h> |
| 46 #include <objbase.h> | 46 #include <objbase.h> |
| 47 | 47 |
| 48 #if defined(USE_SYSTEM_LIBBZ2) | 48 #if defined(USE_SYSTEM_LIBBZ2) |
| 49 #include <bzlib.h> | 49 #include <bzlib.h> |
| 50 #else | 50 #else |
| 51 #include "third_party/bzip2/bzlib.h" | 51 #include "third_party/bzip2/bzlib.h" |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 #include "base/file_version_info.h" | 54 #include "base/file_version_info.h" |
| 55 #include "base/lock.h" |
| 55 #include "base/string_util.h" | 56 #include "base/string_util.h" |
| 56 #include "base/thread.h" | 57 #include "base/thread.h" |
| 57 #include "base/string_number_conversions.h" | 58 #include "base/string_number_conversions.h" |
| 58 #include "base/utf_string_conversions.h" | 59 #include "base/utf_string_conversions.h" |
| 59 #include "chrome/common/chrome_version_info.h" | 60 #include "chrome/common/chrome_version_info.h" |
| 60 #include "chrome/common/net/url_fetcher.h" | 61 #include "chrome/common/net/url_fetcher.h" |
| 61 #include "chrome/common/net/url_fetcher_protect.h" | 62 #include "chrome/common/net/url_fetcher_protect.h" |
| 62 #include "chrome/common/net/url_request_context_getter.h" | 63 #include "chrome/common/net/url_request_context_getter.h" |
| 63 #include "chrome/installer/util/browser_distribution.h" | 64 #include "chrome/installer/util/browser_distribution.h" |
| 64 #include "chrome/installer/util/chrome_frame_distribution.h" | 65 #include "chrome/installer/util/chrome_frame_distribution.h" |
| (...skipping 18 matching lines...) Expand all Loading... |
| 83 using base::TimeDelta; | 84 using base::TimeDelta; |
| 84 | 85 |
| 85 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; | 86 static const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; |
| 86 | 87 |
| 87 // The first UMA upload occurs after this interval. | 88 // The first UMA upload occurs after this interval. |
| 88 static const int kInitialUMAUploadTimeoutMilliSeconds = 30000; | 89 static const int kInitialUMAUploadTimeoutMilliSeconds = 30000; |
| 89 | 90 |
| 90 // Default to one UMA upload per 10 mins. | 91 // Default to one UMA upload per 10 mins. |
| 91 static const int kMinMilliSecondsPerUMAUpload = 600000; | 92 static const int kMinMilliSecondsPerUMAUpload = 600000; |
| 92 | 93 |
| 93 base::LazyInstance<base::ThreadLocalPointer<MetricsService> > | 94 base::LazyInstance<MetricsService> |
| 94 MetricsService::g_metrics_instance_(base::LINKER_INITIALIZED); | 95 g_metrics_instance_(base::LINKER_INITIALIZED); |
| 96 |
| 97 // Traits to create an instance of the ChromeFrame upload thread. |
| 98 struct UploadThreadInstanceTraits |
| 99 : public base::DefaultLazyInstanceTraits<base::Thread> { |
| 100 static base::Thread* New(void* instance) { |
| 101 // Use placement new to initialize our instance in our preallocated space. |
| 102 // The parenthesis is very important here to force POD type initialization. |
| 103 base::Thread* upload_thread = |
| 104 new (instance) base::Thread("ChromeFrameUploadThread"); |
| 105 base::Thread::Options options; |
| 106 options.message_loop_type = MessageLoop::TYPE_IO; |
| 107 bool ret = upload_thread->StartWithOptions(options); |
| 108 if (!ret) { |
| 109 NOTREACHED() << "Failed to start upload thread"; |
| 110 } |
| 111 return upload_thread; |
| 112 } |
| 113 }; |
| 114 |
| 115 // ChromeFrame UMA uploads occur on this thread. This thread is started on the |
| 116 // IE UI thread. This thread needs to be stopped on the same thread it was |
| 117 // started on. We don't have a good way of achieving this at this point. This |
| 118 // thread object is currently leaked. |
| 119 // TODO(ananta) |
| 120 // Fix this. |
| 121 base::LazyInstance<base::Thread, UploadThreadInstanceTraits> |
| 122 g_metrics_upload_thread_(base::LINKER_INITIALIZED); |
| 123 |
| 124 Lock g_metrics_service_lock; |
| 95 | 125 |
| 96 extern base::LazyInstance<StatisticsRecorder> g_statistics_recorder_; | 126 extern base::LazyInstance<StatisticsRecorder> g_statistics_recorder_; |
| 97 | 127 |
| 98 // This class provides HTTP request context information for metrics upload | 128 // This class provides HTTP request context information for metrics upload |
| 99 // requests initiated by ChromeFrame. | 129 // requests initiated by ChromeFrame. |
| 100 class ChromeFrameUploadRequestContext : public URLRequestContext { | 130 class ChromeFrameUploadRequestContext : public URLRequestContext { |
| 101 public: | 131 public: |
| 102 ChromeFrameUploadRequestContext(MessageLoop* io_loop) | 132 ChromeFrameUploadRequestContext(MessageLoop* io_loop) |
| 103 : io_loop_(io_loop) { | 133 : io_loop_(io_loop) { |
| 104 Initialize(); | 134 Initialize(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 public CWindowImpl<ChromeFrameMetricsDataUploader>, | 232 public CWindowImpl<ChromeFrameMetricsDataUploader>, |
| 203 public TaskMarshallerThroughWindowsMessages< | 233 public TaskMarshallerThroughWindowsMessages< |
| 204 ChromeFrameMetricsDataUploader> { | 234 ChromeFrameMetricsDataUploader> { |
| 205 public: | 235 public: |
| 206 BEGIN_MSG_MAP(ChromeFrameMetricsDataUploader) | 236 BEGIN_MSG_MAP(ChromeFrameMetricsDataUploader) |
| 207 CHAIN_MSG_MAP( | 237 CHAIN_MSG_MAP( |
| 208 TaskMarshallerThroughWindowsMessages<ChromeFrameMetricsDataUploader>) | 238 TaskMarshallerThroughWindowsMessages<ChromeFrameMetricsDataUploader>) |
| 209 END_MSG_MAP() | 239 END_MSG_MAP() |
| 210 | 240 |
| 211 ChromeFrameMetricsDataUploader() | 241 ChromeFrameMetricsDataUploader() |
| 212 : fetcher_(NULL), | 242 : fetcher_(NULL) { |
| 213 upload_thread_("ChromeFrameMetricsUploadThread") { | |
| 214 DLOG(INFO) << __FUNCTION__; | 243 DLOG(INFO) << __FUNCTION__; |
| 215 creator_thread_id_ = PlatformThread::CurrentId(); | 244 creator_thread_id_ = PlatformThread::CurrentId(); |
| 216 } | 245 } |
| 217 | 246 |
| 218 ~ChromeFrameMetricsDataUploader() { | 247 ~ChromeFrameMetricsDataUploader() { |
| 219 DLOG(INFO) << __FUNCTION__; | 248 DLOG(INFO) << __FUNCTION__; |
| 220 DCHECK(creator_thread_id_ == PlatformThread::CurrentId()); | 249 DCHECK(creator_thread_id_ == PlatformThread::CurrentId()); |
| 221 } | 250 } |
| 222 | 251 |
| 223 virtual void OnFinalMessage(HWND wnd) { | 252 virtual void OnFinalMessage(HWND wnd) { |
| 224 Release(); | 253 Release(); |
| 225 } | 254 } |
| 226 | 255 |
| 227 bool Initialize() { | 256 bool Initialize() { |
| 257 bool ret = false; |
| 258 |
| 228 if (!Create(NULL, NULL, NULL, WS_OVERLAPPEDWINDOW)) { | 259 if (!Create(NULL, NULL, NULL, WS_OVERLAPPEDWINDOW)) { |
| 229 NOTREACHED() << "Failed to create window"; | 260 NOTREACHED() << "Failed to create window"; |
| 230 return false; | 261 return ret; |
| 231 } | 262 } |
| 232 DCHECK(IsWindow()); | 263 DCHECK(IsWindow()); |
| 233 | 264 |
| 265 if (!g_metrics_upload_thread_.Get().IsRunning()) { |
| 266 NOTREACHED() << "Upload thread is not running"; |
| 267 return ret; |
| 268 } |
| 269 |
| 270 ret = true; |
| 234 // Grab a reference to the current instance which ensures that it stays | 271 // Grab a reference to the current instance which ensures that it stays |
| 235 // around until the HTTP request initiated below completes. | 272 // around until the HTTP request initiated below completes. |
| 236 // Corresponding Release is in OnFinalMessage. | 273 // Corresponding Release is in OnFinalMessage. |
| 237 AddRef(); | 274 AddRef(); |
| 238 | 275 return ret; |
| 239 base::Thread::Options options; | |
| 240 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 241 return upload_thread_.StartWithOptions(options); | |
| 242 } | 276 } |
| 243 | 277 |
| 244 bool Uninitialize() { | 278 bool Uninitialize() { |
| 245 DestroyWindow(); | 279 DestroyWindow(); |
| 246 return true; | 280 return true; |
| 247 } | 281 } |
| 248 | 282 |
| 249 static HRESULT ChromeFrameMetricsDataUploader::UploadDataHelper( | 283 static HRESULT ChromeFrameMetricsDataUploader::UploadDataHelper( |
| 250 const std::string& upload_data) { | 284 const std::string& upload_data) { |
| 251 scoped_refptr<ChromeFrameMetricsDataUploader> data_uploader = | 285 scoped_refptr<ChromeFrameMetricsDataUploader> data_uploader = |
| 252 new ChromeFrameMetricsDataUploader(); | 286 new ChromeFrameMetricsDataUploader(); |
| 253 | 287 |
| 254 data_uploader->Initialize(); | 288 if (!data_uploader->Initialize()) { |
| 255 DCHECK(data_uploader->upload_thread_.message_loop()); | 289 NOTREACHED() << "Failed to initialize ChromeFrameMetricsDataUploader"; |
| 290 return E_FAIL; |
| 291 } |
| 256 | 292 |
| 257 data_uploader->upload_thread_.message_loop()->PostTask(FROM_HERE, | 293 MessageLoop* io_loop = g_metrics_upload_thread_.Get().message_loop(); |
| 294 if (!io_loop) { |
| 295 NOTREACHED() << "Failed to initialize ChromeFrame UMA upload thread"; |
| 296 return E_FAIL; |
| 297 } |
| 298 |
| 299 io_loop->PostTask( |
| 300 FROM_HERE, |
| 258 NewRunnableMethod(data_uploader.get(), | 301 NewRunnableMethod(data_uploader.get(), |
| 259 &ChromeFrameMetricsDataUploader::UploadData, | 302 &ChromeFrameMetricsDataUploader::UploadData, |
| 260 upload_data)); | 303 upload_data, io_loop)); |
| 261 return S_OK; | 304 return S_OK; |
| 262 } | 305 } |
| 263 | 306 |
| 264 void UploadData(const std::string& upload_data) { | 307 void UploadData(const std::string& upload_data, MessageLoop* message_loop) { |
| 265 DCHECK(fetcher_ == NULL); | 308 DCHECK(fetcher_ == NULL); |
| 309 DCHECK(message_loop != NULL); |
| 266 | 310 |
| 267 BrowserDistribution* dist = ChromeFrameDistribution::GetDistribution(); | 311 BrowserDistribution* dist = ChromeFrameDistribution::GetDistribution(); |
| 268 DCHECK(dist != NULL); | 312 DCHECK(dist != NULL); |
| 269 | 313 |
| 270 fetcher_ = new URLFetcher(GURL(WideToUTF8(dist->GetStatsServerURL())), | 314 fetcher_ = new URLFetcher(GURL(WideToUTF8(dist->GetStatsServerURL())), |
| 271 URLFetcher::POST, this); | 315 URLFetcher::POST, this); |
| 272 | 316 |
| 273 fetcher_->set_request_context(new ChromeFrameUploadRequestContextGetter( | 317 fetcher_->set_request_context(new ChromeFrameUploadRequestContextGetter( |
| 274 upload_thread_.message_loop())); | 318 message_loop)); |
| 275 fetcher_->set_upload_data(kMetricsType, upload_data); | 319 fetcher_->set_upload_data(kMetricsType, upload_data); |
| 276 fetcher_->Start(); | 320 fetcher_->Start(); |
| 277 } | 321 } |
| 278 | 322 |
| 279 // URLFetcher::Delegate | 323 // URLFetcher::Delegate |
| 280 virtual void OnURLFetchComplete(const URLFetcher* source, | 324 virtual void OnURLFetchComplete(const URLFetcher* source, |
| 281 const GURL& url, | 325 const GURL& url, |
| 282 const URLRequestStatus& status, | 326 const URLRequestStatus& status, |
| 283 int response_code, | 327 int response_code, |
| 284 const ResponseCookies& cookies, | 328 const ResponseCookies& cookies, |
| 285 const std::string& data) { | 329 const std::string& data) { |
| 286 DLOG(INFO) << __FUNCTION__ | 330 DLOG(INFO) << __FUNCTION__ |
| 287 << StringPrintf(": url : %hs, status:%d, response code: %d\n", | 331 << StringPrintf(": url : %hs, status:%d, response code: %d\n", |
| 288 url.spec().c_str(), status.status(), | 332 url.spec().c_str(), status.status(), |
| 289 response_code); | 333 response_code); |
| 290 delete fetcher_; | 334 delete fetcher_; |
| 291 fetcher_ = NULL; | 335 fetcher_ = NULL; |
| 292 | 336 |
| 293 PostTask(FROM_HERE, | 337 PostTask(FROM_HERE, |
| 294 NewRunnableMethod(this, | 338 NewRunnableMethod(this, |
| 295 &ChromeFrameMetricsDataUploader::Uninitialize)); | 339 &ChromeFrameMetricsDataUploader::Uninitialize)); |
| 296 } | 340 } |
| 297 | 341 |
| 298 private: | 342 private: |
| 299 base::Thread upload_thread_; | |
| 300 URLFetcher* fetcher_; | 343 URLFetcher* fetcher_; |
| 301 PlatformThreadId creator_thread_id_; | 344 PlatformThreadId creator_thread_id_; |
| 302 }; | 345 }; |
| 303 | 346 |
| 304 MetricsService* MetricsService::GetInstance() { | 347 MetricsService* MetricsService::GetInstance() { |
| 305 if (g_metrics_instance_.Pointer()->Get()) | 348 AutoLock lock(g_metrics_service_lock); |
| 306 return g_metrics_instance_.Pointer()->Get(); | 349 return &g_metrics_instance_.Get(); |
| 307 | |
| 308 g_metrics_instance_.Pointer()->Set(new MetricsService); | |
| 309 return g_metrics_instance_.Pointer()->Get(); | |
| 310 } | 350 } |
| 311 | 351 |
| 312 MetricsService::MetricsService() | 352 MetricsService::MetricsService() |
| 313 : recording_active_(false), | 353 : recording_active_(false), |
| 314 reporting_active_(false), | 354 reporting_active_(false), |
| 315 user_permits_upload_(false), | 355 user_permits_upload_(false), |
| 316 state_(INITIALIZED), | 356 state_(INITIALIZED), |
| 317 thread_(NULL), | 357 thread_(NULL), |
| 318 initial_uma_upload_(true), | 358 initial_uma_upload_(true), |
| 319 transmission_timer_id_(0) { | 359 transmission_timer_id_(0) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 336 | 376 |
| 337 thread_ = PlatformThread::CurrentId(); | 377 thread_ = PlatformThread::CurrentId(); |
| 338 | 378 |
| 339 user_permits_upload_ = GoogleUpdateSettings::GetCollectStatsConsent(); | 379 user_permits_upload_ = GoogleUpdateSettings::GetCollectStatsConsent(); |
| 340 // Update session ID | 380 // Update session ID |
| 341 session_id_ = CrashMetricsReporter::GetInstance()->IncrementMetric( | 381 session_id_ = CrashMetricsReporter::GetInstance()->IncrementMetric( |
| 342 CrashMetricsReporter::SESSION_ID); | 382 CrashMetricsReporter::SESSION_ID); |
| 343 | 383 |
| 344 // Ensure that an instance of the StatisticsRecorder object is created. | 384 // Ensure that an instance of the StatisticsRecorder object is created. |
| 345 g_statistics_recorder_.Get(); | 385 g_statistics_recorder_.Get(); |
| 386 |
| 387 if (user_permits_upload_) { |
| 388 // Ensure that an instance of the metrics upload thread is created. |
| 389 g_metrics_upload_thread_.Get(); |
| 390 } |
| 391 |
| 346 CrashMetricsReporter::GetInstance()->set_active(true); | 392 CrashMetricsReporter::GetInstance()->set_active(true); |
| 347 } | 393 } |
| 348 | 394 |
| 349 // static | 395 // static |
| 350 void MetricsService::Start() { | 396 void MetricsService::Start() { |
| 351 if (GetInstance()->state_ == ACTIVE) | 397 if (GetInstance()->state_ == ACTIVE) |
| 352 return; | 398 return; |
| 353 | 399 |
| 354 GetInstance()->InitializeMetricsState(); | 400 GetInstance()->InitializeMetricsState(); |
| 355 GetInstance()->SetRecording(true); | 401 GetInstance()->SetRecording(true); |
| 356 GetInstance()->SetReporting(true); | 402 GetInstance()->SetReporting(true); |
| 357 } | 403 } |
| 358 | 404 |
| 359 // static | 405 // static |
| 360 void MetricsService::Stop() { | 406 void MetricsService::Stop() { |
| 361 GetInstance()->SetReporting(false); | 407 GetInstance()->SetReporting(false); |
| 362 GetInstance()->SetRecording(false); | 408 GetInstance()->SetRecording(false); |
| 363 } | 409 } |
| 364 | 410 |
| 365 void MetricsService::SetRecording(bool enabled) { | 411 void MetricsService::SetRecording(bool enabled) { |
| 366 DCHECK_EQ(thread_, PlatformThread::CurrentId()); | |
| 367 if (enabled == recording_active_) | 412 if (enabled == recording_active_) |
| 368 return; | 413 return; |
| 369 | 414 |
| 370 if (enabled) { | 415 if (enabled) { |
| 371 if (client_id_.empty()) { | 416 if (client_id_.empty()) { |
| 372 client_id_ = GenerateClientID(); | 417 client_id_ = GenerateClientID(); |
| 373 // Save client id somewhere. | 418 // Save client id somewhere. |
| 374 } | 419 } |
| 375 StartRecording(); | 420 StartRecording(); |
| 376 | 421 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 version += "-F"; | 595 version += "-F"; |
| 551 if (!version_info.IsOfficialBuild()) | 596 if (!version_info.IsOfficialBuild()) |
| 552 version.append("-devel"); | 597 version.append("-devel"); |
| 553 return version; | 598 return version; |
| 554 } else { | 599 } else { |
| 555 NOTREACHED() << "Unable to retrieve version string."; | 600 NOTREACHED() << "Unable to retrieve version string."; |
| 556 } | 601 } |
| 557 | 602 |
| 558 return std::string(); | 603 return std::string(); |
| 559 } | 604 } |
| OLD | NEW |