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/metrics/chrome_metrics_service_client.h" | 5 #include "chrome/browser/metrics/chrome_metrics_service_client.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/threading/platform_thread.h" |
| 10 #include "base/time/time.h" |
8 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
9 #include "chrome/browser/chrome_notification_types.h" | 12 #include "chrome/browser/chrome_notification_types.h" |
10 #include "chrome/browser/google/google_util.h" | 13 #include "chrome/browser/google/google_util.h" |
| 14 #include "chrome/browser/memory_details.h" |
11 #include "chrome/browser/metrics/metrics_service.h" | 15 #include "chrome/browser/metrics/metrics_service.h" |
12 #include "chrome/browser/ui/browser_otr_state.h" | 16 #include "chrome/browser/ui/browser_otr_state.h" |
13 #include "chrome/common/chrome_version_info.h" | 17 #include "chrome/common/chrome_version_info.h" |
14 #include "chrome/common/crash_keys.h" | 18 #include "chrome/common/crash_keys.h" |
| 19 #include "chrome/common/render_messages.h" |
| 20 #include "content/public/browser/histogram_fetcher.h" |
15 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
| 22 #include "content/public/browser/render_process_host.h" |
| 23 |
| 24 #if !defined(OS_ANDROID) |
| 25 #include "chrome/browser/service_process/service_process_control.h" |
| 26 #endif |
16 | 27 |
17 namespace { | 28 namespace { |
18 | 29 |
| 30 // This specifies the amount of time to wait for all renderers to send their |
| 31 // data. |
| 32 const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. |
| 33 |
19 metrics::SystemProfileProto::Channel AsProtobufChannel( | 34 metrics::SystemProfileProto::Channel AsProtobufChannel( |
20 chrome::VersionInfo::Channel channel) { | 35 chrome::VersionInfo::Channel channel) { |
21 switch (channel) { | 36 switch (channel) { |
22 case chrome::VersionInfo::CHANNEL_UNKNOWN: | 37 case chrome::VersionInfo::CHANNEL_UNKNOWN: |
23 return metrics::SystemProfileProto::CHANNEL_UNKNOWN; | 38 return metrics::SystemProfileProto::CHANNEL_UNKNOWN; |
24 case chrome::VersionInfo::CHANNEL_CANARY: | 39 case chrome::VersionInfo::CHANNEL_CANARY: |
25 return metrics::SystemProfileProto::CHANNEL_CANARY; | 40 return metrics::SystemProfileProto::CHANNEL_CANARY; |
26 case chrome::VersionInfo::CHANNEL_DEV: | 41 case chrome::VersionInfo::CHANNEL_DEV: |
27 return metrics::SystemProfileProto::CHANNEL_DEV; | 42 return metrics::SystemProfileProto::CHANNEL_DEV; |
28 case chrome::VersionInfo::CHANNEL_BETA: | 43 case chrome::VersionInfo::CHANNEL_BETA: |
29 return metrics::SystemProfileProto::CHANNEL_BETA; | 44 return metrics::SystemProfileProto::CHANNEL_BETA; |
30 case chrome::VersionInfo::CHANNEL_STABLE: | 45 case chrome::VersionInfo::CHANNEL_STABLE: |
31 return metrics::SystemProfileProto::CHANNEL_STABLE; | 46 return metrics::SystemProfileProto::CHANNEL_STABLE; |
32 } | 47 } |
33 NOTREACHED(); | 48 NOTREACHED(); |
34 return metrics::SystemProfileProto::CHANNEL_UNKNOWN; | 49 return metrics::SystemProfileProto::CHANNEL_UNKNOWN; |
35 } | 50 } |
36 | 51 |
| 52 // Handles asynchronous fetching of memory details. |
| 53 // Will run the provided task after finished. |
| 54 class MetricsMemoryDetails : public MemoryDetails { |
| 55 public: |
| 56 explicit MetricsMemoryDetails(const base::Closure& callback) |
| 57 : callback_(callback) {} |
| 58 |
| 59 virtual void OnDetailsAvailable() OVERRIDE { |
| 60 base::MessageLoop::current()->PostTask(FROM_HERE, callback_); |
| 61 } |
| 62 |
| 63 private: |
| 64 virtual ~MetricsMemoryDetails() {} |
| 65 |
| 66 base::Closure callback_; |
| 67 |
| 68 DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails); |
| 69 }; |
| 70 |
37 } // namespace | 71 } // namespace |
38 | 72 |
39 ChromeMetricsServiceClient::ChromeMetricsServiceClient() : service_(NULL) { | 73 ChromeMetricsServiceClient::ChromeMetricsServiceClient() |
| 74 : service_(NULL), |
| 75 waiting_for_collect_final_metrics_step_(false), |
| 76 num_async_histogram_fetches_in_progress_(0), |
| 77 weak_ptr_factory_(this) { |
| 78 DCHECK(thread_checker_.CalledOnValidThread()); |
40 RegisterForNotifications(); | 79 RegisterForNotifications(); |
41 } | 80 } |
42 | 81 |
43 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() { | 82 ChromeMetricsServiceClient::~ChromeMetricsServiceClient() { |
| 83 DCHECK(thread_checker_.CalledOnValidThread()); |
44 } | 84 } |
45 | 85 |
46 void ChromeMetricsServiceClient::SetClientID(const std::string& client_id) { | 86 void ChromeMetricsServiceClient::SetClientID(const std::string& client_id) { |
47 crash_keys::SetClientID(client_id); | 87 crash_keys::SetClientID(client_id); |
48 } | 88 } |
49 | 89 |
50 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() { | 90 bool ChromeMetricsServiceClient::IsOffTheRecordSessionActive() { |
51 return !chrome::IsOffTheRecordSessionActive(); | 91 return !chrome::IsOffTheRecordSessionActive(); |
52 } | 92 } |
53 | 93 |
(...skipping 23 matching lines...) Expand all Loading... |
77 if (!version_info.IsOfficialBuild()) | 117 if (!version_info.IsOfficialBuild()) |
78 version.append("-devel"); | 118 version.append("-devel"); |
79 return version; | 119 return version; |
80 } | 120 } |
81 | 121 |
82 void ChromeMetricsServiceClient::OnLogUploadComplete() { | 122 void ChromeMetricsServiceClient::OnLogUploadComplete() { |
83 // Collect network stats after each UMA upload. | 123 // Collect network stats after each UMA upload. |
84 network_stats_uploader_.CollectAndReportNetworkStats(); | 124 network_stats_uploader_.CollectAndReportNetworkStats(); |
85 } | 125 } |
86 | 126 |
| 127 void ChromeMetricsServiceClient::CollectFinalMetrics( |
| 128 const base::Closure& done_callback) { |
| 129 DCHECK(thread_checker_.CalledOnValidThread()); |
| 130 |
| 131 collect_final_metrics_done_callback_ = done_callback; |
| 132 |
| 133 // Begin the multi-step process of collecting memory usage histograms: |
| 134 // First spawn a task to collect the memory details; when that task is |
| 135 // finished, it will call OnMemoryDetailCollectionDone. That will in turn |
| 136 // call HistogramSynchronization to collect histograms from all renderers and |
| 137 // then call OnHistogramSynchronizationDone to continue processing. |
| 138 DCHECK(!waiting_for_collect_final_metrics_step_); |
| 139 waiting_for_collect_final_metrics_step_ = true; |
| 140 |
| 141 base::Closure callback = |
| 142 base::Bind(&ChromeMetricsServiceClient::OnMemoryDetailCollectionDone, |
| 143 weak_ptr_factory_.GetWeakPtr()); |
| 144 |
| 145 scoped_refptr<MetricsMemoryDetails> details( |
| 146 new MetricsMemoryDetails(callback)); |
| 147 details->StartFetch(MemoryDetails::UPDATE_USER_METRICS); |
| 148 |
| 149 // Collect WebCore cache information to put into a histogram. |
| 150 for (content::RenderProcessHost::iterator i( |
| 151 content::RenderProcessHost::AllHostsIterator()); |
| 152 !i.IsAtEnd(); i.Advance()) { |
| 153 i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats()); |
| 154 } |
| 155 } |
| 156 |
| 157 void ChromeMetricsServiceClient::OnMemoryDetailCollectionDone() { |
| 158 DCHECK(thread_checker_.CalledOnValidThread()); |
| 159 |
| 160 // This function should only be called as the callback from an ansynchronous |
| 161 // step. |
| 162 DCHECK(waiting_for_collect_final_metrics_step_); |
| 163 |
| 164 // Create a callback_task for OnHistogramSynchronizationDone. |
| 165 base::Closure callback = base::Bind( |
| 166 &ChromeMetricsServiceClient::OnHistogramSynchronizationDone, |
| 167 weak_ptr_factory_.GetWeakPtr()); |
| 168 |
| 169 base::TimeDelta timeout = |
| 170 base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration); |
| 171 |
| 172 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0); |
| 173 |
| 174 #if defined(OS_ANDROID) |
| 175 // Android has no service process. |
| 176 num_async_histogram_fetches_in_progress_ = 1; |
| 177 #else // OS_ANDROID |
| 178 num_async_histogram_fetches_in_progress_ = 2; |
| 179 // Run requests to service and content in parallel. |
| 180 if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) { |
| 181 // Assume |num_async_histogram_fetches_in_progress_| is not changed by |
| 182 // |GetHistograms()|. |
| 183 DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2); |
| 184 // Assign |num_async_histogram_fetches_in_progress_| above and decrement it |
| 185 // here to make code work even if |GetHistograms()| fired |callback|. |
| 186 --num_async_histogram_fetches_in_progress_; |
| 187 } |
| 188 #endif // OS_ANDROID |
| 189 |
| 190 // Set up the callback to task to call after we receive histograms from all |
| 191 // child processes. |timeout| specifies how long to wait before absolutely |
| 192 // calling us back on the task. |
| 193 content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback, |
| 194 timeout); |
| 195 } |
| 196 |
| 197 void ChromeMetricsServiceClient::OnHistogramSynchronizationDone() { |
| 198 DCHECK(thread_checker_.CalledOnValidThread()); |
| 199 |
| 200 // This function should only be called as the callback from an ansynchronous |
| 201 // step. |
| 202 DCHECK(waiting_for_collect_final_metrics_step_); |
| 203 DCHECK_GT(num_async_histogram_fetches_in_progress_, 0); |
| 204 |
| 205 // Check if all expected requests finished. |
| 206 if (--num_async_histogram_fetches_in_progress_ > 0) |
| 207 return; |
| 208 |
| 209 waiting_for_collect_final_metrics_step_ = false; |
| 210 collect_final_metrics_done_callback_.Run(); |
| 211 } |
| 212 |
87 void ChromeMetricsServiceClient::RegisterForNotifications() { | 213 void ChromeMetricsServiceClient::RegisterForNotifications() { |
88 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, | 214 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_OPENED, |
89 content::NotificationService::AllBrowserContextsAndSources()); | 215 content::NotificationService::AllBrowserContextsAndSources()); |
90 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, | 216 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED, |
91 content::NotificationService::AllSources()); | 217 content::NotificationService::AllSources()); |
92 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED, | 218 registrar_.Add(this, chrome::NOTIFICATION_TAB_PARENTED, |
93 content::NotificationService::AllSources()); | 219 content::NotificationService::AllSources()); |
94 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING, | 220 registrar_.Add(this, chrome::NOTIFICATION_TAB_CLOSING, |
95 content::NotificationService::AllSources()); | 221 content::NotificationService::AllSources()); |
96 registrar_.Add(this, content::NOTIFICATION_LOAD_START, | 222 registrar_.Add(this, content::NOTIFICATION_LOAD_START, |
(...skipping 26 matching lines...) Expand all Loading... |
123 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG: | 249 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG: |
124 // TODO(isherman): Remove this NULL check: http://crbug.com/375248 | 250 // TODO(isherman): Remove this NULL check: http://crbug.com/375248 |
125 if (service_) | 251 if (service_) |
126 service_->OnApplicationNotIdle(); | 252 service_->OnApplicationNotIdle(); |
127 break; | 253 break; |
128 | 254 |
129 default: | 255 default: |
130 NOTREACHED(); | 256 NOTREACHED(); |
131 } | 257 } |
132 } | 258 } |
OLD | NEW |