Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / metrics / metrics_service.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //------------------------------------------------------------------------------
6 // Description of the life cycle of a instance of MetricsService.
7 //
8 //  OVERVIEW
9 //
10 // A MetricsService instance is typically created at application startup.  It is
11 // the central controller for the acquisition of log data, and the automatic
12 // transmission of that log data to an external server.  Its major job is to
13 // manage logs, grouping them for transmission, and transmitting them.  As part
14 // of its grouping, MS finalizes logs by including some just-in-time gathered
15 // memory statistics, snapshotting the current stats of numerous histograms,
16 // closing the logs, translating to protocol buffer format, and compressing the
17 // results for transmission.  Transmission includes submitting a compressed log
18 // as data in a URL-post, and retransmitting (or retaining at process
19 // termination) if the attempted transmission failed.  Retention across process
20 // terminations is done using the the PrefServices facilities. The retained logs
21 // (the ones that never got transmitted) are compressed and base64-encoded
22 // before being persisted.
23 //
24 // Logs fall into one of two categories: "initial logs," and "ongoing logs."
25 // There is at most one initial log sent for each complete run of Chrome (from
26 // startup, to browser shutdown).  An initial log is generally transmitted some
27 // short time (1 minute?) after startup, and includes stats such as recent crash
28 // info, the number and types of plugins, etc.  The external server's response
29 // to the initial log conceptually tells this MS if it should continue
30 // transmitting logs (during this session). The server response can actually be
31 // much more detailed, and always includes (at a minimum) how often additional
32 // ongoing logs should be sent.
33 //
34 // After the above initial log, a series of ongoing logs will be transmitted.
35 // The first ongoing log actually begins to accumulate information stating when
36 // the MS was first constructed.  Note that even though the initial log is
37 // commonly sent a full minute after startup, the initial log does not include
38 // much in the way of user stats.   The most common interlog period (delay)
39 // is 30 minutes. That time period starts when the first user action causes a
40 // logging event.  This means that if there is no user action, there may be long
41 // periods without any (ongoing) log transmissions.  Ongoing logs typically
42 // contain very detailed records of user activities (ex: opened tab, closed
43 // tab, fetched URL, maximized window, etc.)  In addition, just before an
44 // ongoing log is closed out, a call is made to gather memory statistics.  Those
45 // memory statistics are deposited into a histogram, and the log finalization
46 // code is then called.  In the finalization, a call to a Histogram server
47 // acquires a list of all local histograms that have been flagged for upload
48 // to the UMA server.  The finalization also acquires the most recent number
49 // of page loads, along with any counts of renderer or plugin crashes.
50 //
51 // When the browser shuts down, there will typically be a fragment of an ongoing
52 // log that has not yet been transmitted.  At shutdown time, that fragment is
53 // closed (including snapshotting histograms), and persisted, for potential
54 // transmission during a future run of the product.
55 //
56 // There are two slightly abnormal shutdown conditions.  There is a
57 // "disconnected scenario," and a "really fast startup and shutdown" scenario.
58 // In the "never connected" situation, the user has (during the running of the
59 // process) never established an internet connection.  As a result, attempts to
60 // transmit the initial log have failed, and a lot(?) of data has accumulated in
61 // the ongoing log (which didn't yet get closed, because there was never even a
62 // contemplation of sending it).  There is also a kindred "lost connection"
63 // situation, where a loss of connection prevented an ongoing log from being
64 // transmitted, and a (still open) log was stuck accumulating a lot(?) of data,
65 // while the earlier log retried its transmission.  In both of these
66 // disconnected situations, two logs need to be, and are, persistently stored
67 // for future transmission.
68 //
69 // The other unusual shutdown condition, termed "really fast startup and
70 // shutdown," involves the deliberate user termination of the process before
71 // the initial log is even formed or transmitted. In that situation, no logging
72 // is done, but the historical crash statistics remain (unlogged) for inclusion
73 // in a future run's initial log.  (i.e., we don't lose crash stats).
74 //
75 // With the above overview, we can now describe the state machine's various
76 // states, based on the State enum specified in the state_ member.  Those states
77 // are:
78 //
79 //  INITIALIZED,                   // Constructor was called.
80 //  INIT_TASK_SCHEDULED,           // Waiting for deferred init tasks to finish.
81 //  INIT_TASK_DONE,                // Waiting for timer to send initial log.
82 //  SENDING_INITIAL_STABILITY_LOG, // Initial stability log being sent.
83 //  SENDING_INITIAL_METRICS_LOG,   // Initial metrics log being sent.
84 //  SENDING_OLD_LOGS,              // Sending unsent logs from previous session.
85 //  SENDING_CURRENT_LOGS,          // Sending ongoing logs as they acrue.
86 //
87 // In more detail, we have:
88 //
89 //    INITIALIZED,            // Constructor was called.
90 // The MS has been constructed, but has taken no actions to compose the
91 // initial log.
92 //
93 //    INIT_TASK_SCHEDULED,    // Waiting for deferred init tasks to finish.
94 // Typically about 30 seconds after startup, a task is sent to a second thread
95 // (the file thread) to perform deferred (lower priority and slower)
96 // initialization steps such as getting the list of plugins.  That task will
97 // (when complete) make an async callback (via a Task) to indicate the
98 // completion.
99 //
100 //    INIT_TASK_DONE,         // Waiting for timer to send initial log.
101 // The callback has arrived, and it is now possible for an initial log to be
102 // created.  This callback typically arrives back less than one second after
103 // the deferred init task is dispatched.
104 //
105 //    SENDING_INITIAL_STABILITY_LOG,  // Initial stability log being sent.
106 // During initialization, if a crash occurred during the previous session, an
107 // initial stability log will be generated and registered with the log manager.
108 // This state will be entered if a stability log was prepared during metrics
109 // service initialization (in InitializeMetricsRecordingState()) and is waiting
110 // to be transmitted when it's time to send up the first log (per the reporting
111 // scheduler).  If there is no initial stability log (e.g. there was no previous
112 // crash), then this state will be skipped and the state will advance to
113 // SENDING_INITIAL_METRICS_LOG.
114 //
115 //    SENDING_INITIAL_METRICS_LOG,  // Initial metrics log being sent.
116 // This state is entered after the initial metrics log has been composed, and
117 // prepared for transmission.  This happens after SENDING_INITIAL_STABILITY_LOG
118 // if there was an initial stability log (see above).  It is also the case that
119 // any previously unsent logs have been loaded into instance variables for
120 // possible transmission.
121 //
122 //    SENDING_OLD_LOGS,       // Sending unsent logs from previous session.
123 // This state indicates that the initial log for this session has been
124 // successfully sent and it is now time to send any logs that were
125 // saved from previous sessions.  All such logs will be transmitted before
126 // exiting this state, and proceeding with ongoing logs from the current session
127 // (see next state).
128 //
129 //    SENDING_CURRENT_LOGS,   // Sending standard current logs as they accrue.
130 // Current logs are being accumulated.  Typically every 20 minutes a log is
131 // closed and finalized for transmission, at the same time as a new log is
132 // started.
133 //
134 // The progression through the above states is simple, and sequential, in the
135 // most common use cases.  States proceed from INITIAL to SENDING_CURRENT_LOGS,
136 // and remain in the latter until shutdown.
137 //
138 // The one unusual case is when the user asks that we stop logging.  When that
139 // happens, any staged (transmission in progress) log is persisted, and any log
140 // that is currently accumulating is also finalized and persisted.  We then
141 // regress back to the SEND_OLD_LOGS state in case the user enables log
142 // recording again during this session.  This way anything we have persisted
143 // will be sent automatically if/when we progress back to SENDING_CURRENT_LOG
144 // state.
145 //
146 // Another similar case is on mobile, when the application is backgrounded and
147 // then foregrounded again. Backgrounding created new "old" stored logs, so the
148 // state drops back from SENDING_CURRENT_LOGS to SENDING_OLD_LOGS so those logs
149 // will be sent.
150 //
151 // Also note that whenever we successfully send an old log, we mirror the list
152 // of logs into the PrefService. This ensures that IF we crash, we won't start
153 // up and retransmit our old logs again.
154 //
155 // Due to race conditions, it is always possible that a log file could be sent
156 // twice.  For example, if a log file is sent, but not yet acknowledged by
157 // the external server, and the user shuts down, then a copy of the log may be
158 // saved for re-transmission.  These duplicates could be filtered out server
159 // side, but are not expected to be a significant problem.
160 //
161 //
162 //------------------------------------------------------------------------------
163
164 #include "chrome/browser/metrics/metrics_service.h"
165
166 #include <algorithm>
167
168 #include "base/bind.h"
169 #include "base/callback.h"
170 #include "base/command_line.h"
171 #include "base/guid.h"
172 #include "base/md5.h"
173 #include "base/metrics/histogram.h"
174 #include "base/metrics/sparse_histogram.h"
175 #include "base/metrics/statistics_recorder.h"
176 #include "base/prefs/pref_registry_simple.h"
177 #include "base/prefs/pref_service.h"
178 #include "base/prefs/scoped_user_pref_update.h"
179 #include "base/rand_util.h"
180 #include "base/strings/string_number_conversions.h"
181 #include "base/strings/utf_string_conversions.h"
182 #include "base/threading/platform_thread.h"
183 #include "base/threading/thread.h"
184 #include "base/threading/thread_restrictions.h"
185 #include "base/tracked_objects.h"
186 #include "base/values.h"
187 #include "chrome/browser/browser_process.h"
188 #include "chrome/browser/chrome_notification_types.h"
189 #include "chrome/browser/io_thread.h"
190 #include "chrome/browser/memory_details.h"
191 #include "chrome/browser/metrics/compression_utils.h"
192 #include "chrome/browser/metrics/metrics_log.h"
193 #include "chrome/browser/metrics/metrics_log_serializer.h"
194 #include "chrome/browser/metrics/metrics_reporting_scheduler.h"
195 #include "chrome/browser/metrics/time_ticks_experiment_win.h"
196 #include "chrome/browser/metrics/tracking_synchronizer.h"
197 #include "chrome/common/metrics/variations/variations_util.h"
198 #include "chrome/browser/net/http_pipelining_compatibility_client.h"
199 #include "chrome/browser/net/network_stats.h"
200 #include "chrome/browser/omnibox/omnibox_log.h"
201 #include "chrome/browser/ui/browser_list.h"
202 #include "chrome/browser/ui/browser_otr_state.h"
203 #include "chrome/browser/ui/search/search_tab_helper.h"
204 #include "chrome/common/chrome_constants.h"
205 #include "chrome/common/chrome_result_codes.h"
206 #include "chrome/common/chrome_switches.h"
207 #include "chrome/common/crash_keys.h"
208 #include "chrome/common/metrics/caching_permuted_entropy_provider.h"
209 #include "chrome/common/metrics/metrics_log_manager.h"
210 #include "chrome/common/net/test_server_locations.h"
211 #include "chrome/common/pref_names.h"
212 #include "chrome/common/render_messages.h"
213 #include "components/variations/entropy_provider.h"
214 #include "components/variations/metrics_util.h"
215 #include "content/public/browser/child_process_data.h"
216 #include "content/public/browser/histogram_fetcher.h"
217 #include "content/public/browser/load_notification_details.h"
218 #include "content/public/browser/notification_service.h"
219 #include "content/public/browser/plugin_service.h"
220 #include "content/public/browser/render_process_host.h"
221 #include "content/public/browser/user_metrics.h"
222 #include "content/public/browser/web_contents.h"
223 #include "content/public/common/process_type.h"
224 #include "content/public/common/webplugininfo.h"
225 #include "extensions/browser/process_map.h"
226 #include "net/base/load_flags.h"
227 #include "net/url_request/url_fetcher.h"
228
229 // TODO(port): port browser_distribution.h.
230 #if !defined(OS_POSIX)
231 #include "chrome/installer/util/browser_distribution.h"
232 #endif
233
234 #if defined(OS_CHROMEOS)
235 #include "chrome/browser/chromeos/external_metrics.h"
236 #include "chromeos/system/statistics_provider.h"
237 #endif
238
239 #if defined(OS_WIN)
240 #include <windows.h>  // Needed for STATUS_* codes
241 #include "base/win/registry.h"
242 #endif
243
244 #if !defined(OS_ANDROID)
245 #include "chrome/browser/service_process/service_process_control.h"
246 #endif
247
248 using base::Time;
249 using content::BrowserThread;
250 using content::ChildProcessData;
251 using content::LoadNotificationDetails;
252 using content::PluginService;
253
254 namespace {
255
256 // Check to see that we're being called on only one thread.
257 bool IsSingleThreaded() {
258   static base::PlatformThreadId thread_id = 0;
259   if (!thread_id)
260     thread_id = base::PlatformThread::CurrentId();
261   return base::PlatformThread::CurrentId() == thread_id;
262 }
263
264 // The delay, in seconds, after starting recording before doing expensive
265 // initialization work.
266 #if defined(OS_ANDROID) || defined(OS_IOS)
267 // On mobile devices, a significant portion of sessions last less than a minute.
268 // Use a shorter timer on these platforms to avoid losing data.
269 // TODO(dfalcantara): To avoid delaying startup, tighten up initialization so
270 //                    that it occurs after the user gets their initial page.
271 const int kInitializationDelaySeconds = 5;
272 #else
273 const int kInitializationDelaySeconds = 30;
274 #endif
275
276 // This specifies the amount of time to wait for all renderers to send their
277 // data.
278 const int kMaxHistogramGatheringWaitDuration = 60000;  // 60 seconds.
279
280 // The maximum number of events in a log uploaded to the UMA server.
281 const int kEventLimit = 2400;
282
283 // If an upload fails, and the transmission was over this byte count, then we
284 // will discard the log, and not try to retransmit it.  We also don't persist
285 // the log to the prefs for transmission during the next chrome session if this
286 // limit is exceeded.
287 const size_t kUploadLogAvoidRetransmitSize = 50000;
288
289 // Interval, in minutes, between state saves.
290 const int kSaveStateIntervalMinutes = 5;
291
292 enum ResponseStatus {
293   UNKNOWN_FAILURE,
294   SUCCESS,
295   BAD_REQUEST,  // Invalid syntax or log too large.
296   NO_RESPONSE,
297   NUM_RESPONSE_STATUSES
298 };
299
300 ResponseStatus ResponseCodeToStatus(int response_code) {
301   switch (response_code) {
302     case 200:
303       return SUCCESS;
304     case 400:
305       return BAD_REQUEST;
306     case net::URLFetcher::RESPONSE_CODE_INVALID:
307       return NO_RESPONSE;
308     default:
309       return UNKNOWN_FAILURE;
310   }
311 }
312
313 // The argument used to generate a non-identifying entropy source. We want no
314 // more than 13 bits of entropy, so use this max to return a number in the range
315 // [0, 7999] as the entropy source (12.97 bits of entropy).
316 const int kMaxLowEntropySize = 8000;
317
318 // Default prefs value for prefs::kMetricsLowEntropySource to indicate that the
319 // value has not yet been set.
320 const int kLowEntropySourceNotSet = -1;
321
322 // Generates a new non-identifying entropy source used to seed persistent
323 // activities.
324 int GenerateLowEntropySource() {
325   return base::RandInt(0, kMaxLowEntropySize - 1);
326 }
327
328 // Converts an exit code into something that can be inserted into our
329 // histograms (which expect non-negative numbers less than MAX_INT).
330 int MapCrashExitCodeForHistogram(int exit_code) {
331 #if defined(OS_WIN)
332   // Since |abs(STATUS_GUARD_PAGE_VIOLATION) == MAX_INT| it causes problems in
333   // histograms.cc. Solve this by remapping it to a smaller value, which
334   // hopefully doesn't conflict with other codes.
335   if (exit_code == STATUS_GUARD_PAGE_VIOLATION)
336     return 0x1FCF7EC3;  // Randomly picked number.
337 #endif
338
339   return std::abs(exit_code);
340 }
341
342 void MarkAppCleanShutdownAndCommit() {
343   PrefService* pref = g_browser_process->local_state();
344   pref->SetBoolean(prefs::kStabilityExitedCleanly, true);
345   pref->SetInteger(prefs::kStabilityExecutionPhase,
346                    MetricsService::SHUTDOWN_COMPLETE);
347   // Start writing right away (write happens on a different thread).
348   pref->CommitPendingWrite();
349 }
350
351 // Returns whether initial stability metrics should be sent in a separate log.
352 bool SendSeparateInitialStabilityLog() {
353   return base::FieldTrialList::FindFullName("UMAStability") == "SeparateLog";
354 }
355
356 }  // namespace
357
358
359 SyntheticTrialGroup::SyntheticTrialGroup(uint32 trial,
360                                          uint32 group,
361                                          base::TimeTicks start)
362     : start_time(start) {
363   id.name = trial;
364   id.group = group;
365 }
366
367 SyntheticTrialGroup::~SyntheticTrialGroup() {
368 }
369
370 // static
371 MetricsService::ShutdownCleanliness MetricsService::clean_shutdown_status_ =
372     MetricsService::CLEANLY_SHUTDOWN;
373
374 MetricsService::ExecutionPhase MetricsService::execution_phase_ =
375     MetricsService::UNINITIALIZED_PHASE;
376
377 // This is used to quickly log stats from child process related notifications in
378 // MetricsService::child_stats_buffer_.  The buffer's contents are transferred
379 // out when Local State is periodically saved.  The information is then
380 // reported to the UMA server on next launch.
381 struct MetricsService::ChildProcessStats {
382  public:
383   explicit ChildProcessStats(int process_type)
384       : process_launches(0),
385         process_crashes(0),
386         instances(0),
387         loading_errors(0),
388         process_type(process_type) {}
389
390   // This constructor is only used by the map to return some default value for
391   // an index for which no value has been assigned.
392   ChildProcessStats()
393       : process_launches(0),
394         process_crashes(0),
395         instances(0),
396         loading_errors(0),
397         process_type(content::PROCESS_TYPE_UNKNOWN) {}
398
399   // The number of times that the given child process has been launched
400   int process_launches;
401
402   // The number of times that the given child process has crashed
403   int process_crashes;
404
405   // The number of instances of this child process that have been created.
406   // An instance is a DOM object rendered by this child process during a page
407   // load.
408   int instances;
409
410   // The number of times there was an error loading an instance of this child
411   // process.
412   int loading_errors;
413
414   int process_type;
415 };
416
417 // Handles asynchronous fetching of memory details.
418 // Will run the provided task after finished.
419 class MetricsMemoryDetails : public MemoryDetails {
420  public:
421   explicit MetricsMemoryDetails(const base::Closure& callback)
422       : callback_(callback) {}
423
424   virtual void OnDetailsAvailable() OVERRIDE {
425     base::MessageLoop::current()->PostTask(FROM_HERE, callback_);
426   }
427
428  private:
429   virtual ~MetricsMemoryDetails() {}
430
431   base::Closure callback_;
432   DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails);
433 };
434
435 // static
436 void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
437   DCHECK(IsSingleThreaded());
438   registry->RegisterStringPref(prefs::kMetricsClientID, std::string());
439   registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
440                                 kLowEntropySourceNotSet);
441   registry->RegisterInt64Pref(prefs::kMetricsClientIDTimestamp, 0);
442   registry->RegisterInt64Pref(prefs::kStabilityLaunchTimeSec, 0);
443   registry->RegisterInt64Pref(prefs::kStabilityLastTimestampSec, 0);
444   registry->RegisterStringPref(prefs::kStabilityStatsVersion, std::string());
445   registry->RegisterInt64Pref(prefs::kStabilityStatsBuildTime, 0);
446   registry->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true);
447   registry->RegisterIntegerPref(prefs::kStabilityExecutionPhase,
448                                 UNINITIALIZED_PHASE);
449   registry->RegisterBooleanPref(prefs::kStabilitySessionEndCompleted, true);
450   registry->RegisterIntegerPref(prefs::kMetricsSessionID, -1);
451   registry->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0);
452   registry->RegisterIntegerPref(prefs::kStabilityCrashCount, 0);
453   registry->RegisterIntegerPref(prefs::kStabilityIncompleteSessionEndCount, 0);
454   registry->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0);
455   registry->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0);
456   registry->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount,
457                                 0);
458   registry->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0);
459   registry->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0);
460   registry->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationFail, 0);
461   registry->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationSuccess,
462                                 0);
463   registry->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0);
464   registry->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0);
465 #if defined(OS_CHROMEOS)
466   registry->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0);
467   registry->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0);
468   registry->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount, 0);
469 #endif  // OS_CHROMEOS
470
471   registry->RegisterStringPref(prefs::kStabilitySavedSystemProfile,
472                                std::string());
473   registry->RegisterStringPref(prefs::kStabilitySavedSystemProfileHash,
474                                std::string());
475
476   registry->RegisterListPref(prefs::kMetricsInitialLogs);
477   registry->RegisterListPref(prefs::kMetricsOngoingLogs);
478
479   registry->RegisterInt64Pref(prefs::kInstallDate, 0);
480   registry->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0);
481   registry->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0);
482   registry->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0);
483   registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0);
484   registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0);
485
486 #if defined(OS_ANDROID)
487   RegisterPrefsAndroid(registry);
488 #endif  // defined(OS_ANDROID)
489 }
490
491 // static
492 void MetricsService::DiscardOldStabilityStats(PrefService* local_state) {
493   local_state->SetBoolean(prefs::kStabilityExitedCleanly, true);
494   local_state->SetInteger(prefs::kStabilityExecutionPhase, UNINITIALIZED_PHASE);
495   local_state->SetBoolean(prefs::kStabilitySessionEndCompleted, true);
496
497   local_state->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
498   local_state->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0);
499   local_state->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0);
500   local_state->SetInteger(prefs::kStabilityDebuggerPresent, 0);
501   local_state->SetInteger(prefs::kStabilityDebuggerNotPresent, 0);
502
503   local_state->SetInteger(prefs::kStabilityLaunchCount, 0);
504   local_state->SetInteger(prefs::kStabilityCrashCount, 0);
505
506   local_state->SetInteger(prefs::kStabilityPageLoadCount, 0);
507   local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0);
508   local_state->SetInteger(prefs::kStabilityRendererHangCount, 0);
509
510   local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0);
511   local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0);
512
513   local_state->ClearPref(prefs::kStabilityPluginStats);
514
515   local_state->ClearPref(prefs::kMetricsInitialLogs);
516   local_state->ClearPref(prefs::kMetricsOngoingLogs);
517
518 #if defined(OS_ANDROID)
519   DiscardOldStabilityStatsAndroid(local_state);
520 #endif  // defined(OS_ANDROID)
521 }
522
523 MetricsService::MetricsService()
524     : recording_active_(false),
525       reporting_active_(false),
526       test_mode_active_(false),
527       state_(INITIALIZED),
528       has_initial_stability_log_(false),
529       low_entropy_source_(kLowEntropySourceNotSet),
530       idle_since_last_transmission_(false),
531       session_id_(-1),
532       next_window_id_(0),
533       self_ptr_factory_(this),
534       state_saver_factory_(this),
535       waiting_for_asynchronous_reporting_step_(false),
536       num_async_histogram_fetches_in_progress_(0),
537       entropy_source_returned_(LAST_ENTROPY_NONE) {
538   DCHECK(IsSingleThreaded());
539
540   log_manager_.set_log_serializer(new MetricsLogSerializer);
541   log_manager_.set_max_ongoing_log_store_size(kUploadLogAvoidRetransmitSize);
542
543   BrowserChildProcessObserver::Add(this);
544 }
545
546 MetricsService::~MetricsService() {
547   DisableRecording();
548
549   BrowserChildProcessObserver::Remove(this);
550 }
551
552 void MetricsService::InitializeMetricsRecordingState(
553     ReportingState reporting_state) {
554   InitializeMetricsState(reporting_state);
555
556   base::Closure callback = base::Bind(&MetricsService::StartScheduledUpload,
557                                       self_ptr_factory_.GetWeakPtr());
558   scheduler_.reset(new MetricsReportingScheduler(callback));
559 }
560
561 void MetricsService::Start() {
562   HandleIdleSinceLastTransmission(false);
563   EnableRecording();
564   EnableReporting();
565 }
566
567 void MetricsService::StartRecordingForTests() {
568   test_mode_active_ = true;
569   EnableRecording();
570   DisableReporting();
571 }
572
573 void MetricsService::Stop() {
574   HandleIdleSinceLastTransmission(false);
575   DisableReporting();
576   DisableRecording();
577 }
578
579 void MetricsService::EnableReporting() {
580   if (reporting_active_)
581     return;
582   reporting_active_ = true;
583   StartSchedulerIfNecessary();
584 }
585
586 void MetricsService::DisableReporting() {
587   reporting_active_ = false;
588 }
589
590 std::string MetricsService::GetClientId() {
591   return client_id_;
592 }
593
594 scoped_ptr<const base::FieldTrial::EntropyProvider>
595 MetricsService::CreateEntropyProvider(ReportingState reporting_state) {
596   // For metrics reporting-enabled users, we combine the client ID and low
597   // entropy source to get the final entropy source. Otherwise, only use the low
598   // entropy source.
599   // This has two useful properties:
600   //  1) It makes the entropy source less identifiable for parties that do not
601   //     know the low entropy source.
602   //  2) It makes the final entropy source resettable.
603   const int low_entropy_source_value = GetLowEntropySource();
604   UMA_HISTOGRAM_SPARSE_SLOWLY("UMA.LowEntropySourceValue",
605                               low_entropy_source_value);
606   if (reporting_state == REPORTING_ENABLED) {
607     if (entropy_source_returned_ == LAST_ENTROPY_NONE)
608       entropy_source_returned_ = LAST_ENTROPY_HIGH;
609     DCHECK_EQ(LAST_ENTROPY_HIGH, entropy_source_returned_);
610     const std::string high_entropy_source =
611         client_id_ + base::IntToString(low_entropy_source_value);
612     return scoped_ptr<const base::FieldTrial::EntropyProvider>(
613         new metrics::SHA1EntropyProvider(high_entropy_source));
614   }
615
616   if (entropy_source_returned_ == LAST_ENTROPY_NONE)
617     entropy_source_returned_ = LAST_ENTROPY_LOW;
618   DCHECK_EQ(LAST_ENTROPY_LOW, entropy_source_returned_);
619
620 #if defined(OS_ANDROID) || defined(OS_IOS)
621   return scoped_ptr<const base::FieldTrial::EntropyProvider>(
622       new metrics::CachingPermutedEntropyProvider(
623           g_browser_process->local_state(),
624           low_entropy_source_value,
625           kMaxLowEntropySize));
626 #else
627   return scoped_ptr<const base::FieldTrial::EntropyProvider>(
628       new metrics::PermutedEntropyProvider(low_entropy_source_value,
629                                            kMaxLowEntropySize));
630 #endif
631 }
632
633 void MetricsService::ForceClientIdCreation() {
634   if (!client_id_.empty())
635     return;
636   PrefService* pref = g_browser_process->local_state();
637   client_id_ = pref->GetString(prefs::kMetricsClientID);
638   if (!client_id_.empty())
639     return;
640
641   client_id_ = GenerateClientID();
642   pref->SetString(prefs::kMetricsClientID, client_id_);
643
644   // Might as well make a note of how long this ID has existed
645   pref->SetString(prefs::kMetricsClientIDTimestamp,
646                   base::Int64ToString(Time::Now().ToTimeT()));
647 }
648
649 void MetricsService::EnableRecording() {
650   DCHECK(IsSingleThreaded());
651
652   if (recording_active_)
653     return;
654   recording_active_ = true;
655
656   ForceClientIdCreation();
657   crash_keys::SetClientID(client_id_);
658   if (!log_manager_.current_log())
659     OpenNewLog();
660
661   SetUpNotifications(&registrar_, this);
662   base::RemoveActionCallback(action_callback_);
663   action_callback_ = base::Bind(&MetricsService::OnUserAction,
664                                 base::Unretained(this));
665   base::AddActionCallback(action_callback_);
666 }
667
668 void MetricsService::DisableRecording() {
669   DCHECK(IsSingleThreaded());
670
671   if (!recording_active_)
672     return;
673   recording_active_ = false;
674
675   base::RemoveActionCallback(action_callback_);
676   registrar_.RemoveAll();
677   PushPendingLogsToPersistentStorage();
678   DCHECK(!log_manager_.has_staged_log());
679 }
680
681 bool MetricsService::recording_active() const {
682   DCHECK(IsSingleThreaded());
683   return recording_active_;
684 }
685
686 bool MetricsService::reporting_active() const {
687   DCHECK(IsSingleThreaded());
688   return reporting_active_;
689 }
690
691 // static
692 void MetricsService::SetUpNotifications(
693     content::NotificationRegistrar* registrar,
694     content::NotificationObserver* observer) {
695   registrar->Add(observer, chrome::NOTIFICATION_BROWSER_OPENED,
696                  content::NotificationService::AllBrowserContextsAndSources());
697   registrar->Add(observer, chrome::NOTIFICATION_BROWSER_CLOSED,
698                  content::NotificationService::AllSources());
699   registrar->Add(observer, chrome::NOTIFICATION_TAB_PARENTED,
700                  content::NotificationService::AllSources());
701   registrar->Add(observer, chrome::NOTIFICATION_TAB_CLOSING,
702                  content::NotificationService::AllSources());
703   registrar->Add(observer, content::NOTIFICATION_LOAD_START,
704                  content::NotificationService::AllSources());
705   registrar->Add(observer, content::NOTIFICATION_LOAD_STOP,
706                  content::NotificationService::AllSources());
707   registrar->Add(observer, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
708                  content::NotificationService::AllSources());
709   registrar->Add(observer, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
710                  content::NotificationService::AllSources());
711   registrar->Add(observer, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
712                  content::NotificationService::AllSources());
713 }
714
715 void MetricsService::BrowserChildProcessHostConnected(
716     const content::ChildProcessData& data) {
717   GetChildProcessStats(data).process_launches++;
718 }
719
720 void MetricsService::BrowserChildProcessCrashed(
721     const content::ChildProcessData& data) {
722   GetChildProcessStats(data).process_crashes++;
723   // Exclude plugin crashes from the count below because we report them via
724   // a separate UMA metric.
725   if (!IsPluginProcess(data.process_type))
726     IncrementPrefValue(prefs::kStabilityChildProcessCrashCount);
727 }
728
729 void MetricsService::BrowserChildProcessInstanceCreated(
730     const content::ChildProcessData& data) {
731   GetChildProcessStats(data).instances++;
732 }
733
734 void MetricsService::Observe(int type,
735                              const content::NotificationSource& source,
736                              const content::NotificationDetails& details) {
737   DCHECK(log_manager_.current_log());
738   DCHECK(IsSingleThreaded());
739
740   if (!CanLogNotification())
741     return;
742
743   switch (type) {
744     case chrome::NOTIFICATION_BROWSER_OPENED:
745     case chrome::NOTIFICATION_BROWSER_CLOSED:
746     case chrome::NOTIFICATION_TAB_PARENTED:
747     case chrome::NOTIFICATION_TAB_CLOSING:
748     case content::NOTIFICATION_LOAD_STOP:
749       // These notifications are currently used only to break out of idle mode.
750       break;
751
752     case content::NOTIFICATION_LOAD_START: {
753       content::NavigationController* controller =
754           content::Source<content::NavigationController>(source).ptr();
755       content::WebContents* web_contents = controller->GetWebContents();
756       LogLoadStarted(web_contents);
757       break;
758     }
759
760     case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
761         content::RenderProcessHost::RendererClosedDetails* process_details =
762             content::Details<
763                 content::RenderProcessHost::RendererClosedDetails>(
764                     details).ptr();
765         content::RenderProcessHost* host =
766             content::Source<content::RenderProcessHost>(source).ptr();
767         LogRendererCrash(
768             host, process_details->status, process_details->exit_code);
769       }
770       break;
771
772     case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG:
773       LogRendererHang();
774       break;
775
776     case chrome::NOTIFICATION_OMNIBOX_OPENED_URL: {
777       MetricsLog* current_log =
778           static_cast<MetricsLog*>(log_manager_.current_log());
779       DCHECK(current_log);
780       current_log->RecordOmniboxOpenedURL(
781           *content::Details<OmniboxLog>(details).ptr());
782       break;
783     }
784
785     default:
786       NOTREACHED();
787       break;
788   }
789
790   HandleIdleSinceLastTransmission(false);
791 }
792
793 void MetricsService::HandleIdleSinceLastTransmission(bool in_idle) {
794   // If there wasn't a lot of action, maybe the computer was asleep, in which
795   // case, the log transmissions should have stopped.  Here we start them up
796   // again.
797   if (!in_idle && idle_since_last_transmission_)
798     StartSchedulerIfNecessary();
799   idle_since_last_transmission_ = in_idle;
800 }
801
802 void MetricsService::RecordStartOfSessionEnd() {
803   LogCleanShutdown();
804   RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false);
805 }
806
807 void MetricsService::RecordCompletedSessionEnd() {
808   LogCleanShutdown();
809   RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true);
810 }
811
812 #if defined(OS_ANDROID) || defined(OS_IOS)
813 void MetricsService::OnAppEnterBackground() {
814   scheduler_->Stop();
815
816   MarkAppCleanShutdownAndCommit();
817
818   // At this point, there's no way of knowing when the process will be
819   // killed, so this has to be treated similar to a shutdown, closing and
820   // persisting all logs. Unlinke a shutdown, the state is primed to be ready
821   // to continue logging and uploading if the process does return.
822   if (recording_active() && state_ >= SENDING_INITIAL_STABILITY_LOG) {
823     PushPendingLogsToPersistentStorage();
824     // Persisting logs closes the current log, so start recording a new log
825     // immediately to capture any background work that might be done before the
826     // process is killed.
827     OpenNewLog();
828   }
829 }
830
831 void MetricsService::OnAppEnterForeground() {
832   PrefService* pref = g_browser_process->local_state();
833   pref->SetBoolean(prefs::kStabilityExitedCleanly, false);
834
835   StartSchedulerIfNecessary();
836 }
837 #else
838 void MetricsService::LogNeedForCleanShutdown() {
839   PrefService* pref = g_browser_process->local_state();
840   pref->SetBoolean(prefs::kStabilityExitedCleanly, false);
841   // Redundant setting to be sure we call for a clean shutdown.
842   clean_shutdown_status_ = NEED_TO_SHUTDOWN;
843 }
844 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
845
846 // static
847 void MetricsService::SetExecutionPhase(ExecutionPhase execution_phase) {
848   execution_phase_ = execution_phase;
849   PrefService* pref = g_browser_process->local_state();
850   pref->SetInteger(prefs::kStabilityExecutionPhase, execution_phase_);
851 }
852
853 void MetricsService::RecordBreakpadRegistration(bool success) {
854   if (!success)
855     IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail);
856   else
857     IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess);
858 }
859
860 void MetricsService::RecordBreakpadHasDebugger(bool has_debugger) {
861   if (!has_debugger)
862     IncrementPrefValue(prefs::kStabilityDebuggerNotPresent);
863   else
864     IncrementPrefValue(prefs::kStabilityDebuggerPresent);
865 }
866
867 #if defined(OS_WIN)
868 void MetricsService::CountBrowserCrashDumpAttempts() {
869   // Open the registry key for iteration.
870   base::win::RegKey regkey;
871   if (regkey.Open(HKEY_CURRENT_USER,
872                   chrome::kBrowserCrashDumpAttemptsRegistryPath,
873                   KEY_ALL_ACCESS) != ERROR_SUCCESS) {
874     return;
875   }
876
877   // The values we're interested in counting are all prefixed with the version.
878   base::string16 chrome_version(base::ASCIIToUTF16(chrome::kChromeVersion));
879
880   // Track a list of values to delete. We don't modify the registry key while
881   // we're iterating over its values.
882   typedef std::vector<base::string16> StringVector;
883   StringVector to_delete;
884
885   // Iterate over the values in the key counting dumps with and without crashes.
886   // We directly walk the values instead of using RegistryValueIterator in order
887   // to read all of the values as DWORDS instead of strings.
888   base::string16 name;
889   DWORD value = 0;
890   int dumps_with_crash = 0;
891   int dumps_with_no_crash = 0;
892   for (int i = regkey.GetValueCount() - 1; i >= 0; --i) {
893     if (regkey.GetValueNameAt(i, &name) == ERROR_SUCCESS &&
894         StartsWith(name, chrome_version, false) &&
895         regkey.ReadValueDW(name.c_str(), &value) == ERROR_SUCCESS) {
896       to_delete.push_back(name);
897       if (value == 0)
898         ++dumps_with_no_crash;
899       else
900         ++dumps_with_crash;
901     }
902   }
903
904   // Delete the registry keys we've just counted.
905   for (StringVector::iterator i = to_delete.begin(); i != to_delete.end(); ++i)
906     regkey.DeleteValue(i->c_str());
907
908   // Capture the histogram samples.
909   if (dumps_with_crash != 0)
910     UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithCrash", dumps_with_crash);
911   if (dumps_with_no_crash != 0)
912     UMA_HISTOGRAM_COUNTS("Chrome.BrowserDumpsWithNoCrash", dumps_with_no_crash);
913   int total_dumps = dumps_with_crash + dumps_with_no_crash;
914   if (total_dumps != 0)
915     UMA_HISTOGRAM_COUNTS("Chrome.BrowserCrashDumpAttempts", total_dumps);
916 }
917 #endif  // defined(OS_WIN)
918
919 //------------------------------------------------------------------------------
920 // private methods
921 //------------------------------------------------------------------------------
922
923
924 //------------------------------------------------------------------------------
925 // Initialization methods
926
927 void MetricsService::InitializeMetricsState(ReportingState reporting_state) {
928 #if defined(OS_POSIX)
929   network_stats_server_ = chrome_common_net::kEchoTestServerLocation;
930   http_pipelining_test_server_ = chrome_common_net::kPipelineTestServerBaseUrl;
931 #else
932   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
933   network_stats_server_ = dist->GetNetworkStatsServer();
934   http_pipelining_test_server_ = dist->GetHttpPipeliningTestServer();
935 #endif
936
937   PrefService* pref = g_browser_process->local_state();
938   DCHECK(pref);
939
940   // TODO(asvitkine): Kill this logic when SendSeparateInitialStabilityLog() is
941   // is made the default behavior.
942   if ((pref->GetInt64(prefs::kStabilityStatsBuildTime)
943        != MetricsLog::GetBuildTime()) ||
944       (pref->GetString(prefs::kStabilityStatsVersion)
945        != MetricsLog::GetVersionString())) {
946     // This is a new version, so we don't want to confuse the stats about the
947     // old version with info that we upload.
948     DiscardOldStabilityStats(pref);
949     pref->SetString(prefs::kStabilityStatsVersion,
950                     MetricsLog::GetVersionString());
951     pref->SetInt64(prefs::kStabilityStatsBuildTime,
952                    MetricsLog::GetBuildTime());
953   }
954
955   session_id_ = pref->GetInteger(prefs::kMetricsSessionID);
956
957 #if defined(OS_ANDROID)
958   LogAndroidStabilityToPrefs(pref);
959 #endif  // defined(OS_ANDROID)
960
961   if (!pref->GetBoolean(prefs::kStabilityExitedCleanly)) {
962     IncrementPrefValue(prefs::kStabilityCrashCount);
963     // Reset flag, and wait until we call LogNeedForCleanShutdown() before
964     // monitoring.
965     pref->SetBoolean(prefs::kStabilityExitedCleanly, true);
966
967     // TODO(rtenneti): On windows, consider saving/getting execution_phase from
968     // the registry.
969     int execution_phase = pref->GetInteger(prefs::kStabilityExecutionPhase);
970     UMA_HISTOGRAM_SPARSE_SLOWLY("Chrome.Browser.CrashedExecutionPhase",
971                                 execution_phase);
972
973     // If the previous session didn't exit cleanly, then prepare an initial
974     // stability log if UMA is enabled.
975     bool reporting_will_be_enabled = (reporting_state == REPORTING_ENABLED);
976     if (reporting_will_be_enabled && SendSeparateInitialStabilityLog())
977       PrepareInitialStabilityLog();
978   }
979
980   // Update session ID.
981   ++session_id_;
982   pref->SetInteger(prefs::kMetricsSessionID, session_id_);
983
984   // Stability bookkeeping
985   IncrementPrefValue(prefs::kStabilityLaunchCount);
986
987   DCHECK_EQ(UNINITIALIZED_PHASE, execution_phase_);
988   SetExecutionPhase(START_METRICS_RECORDING);
989
990 #if defined(OS_WIN)
991   CountBrowserCrashDumpAttempts();
992 #endif  // defined(OS_WIN)
993
994   if (!pref->GetBoolean(prefs::kStabilitySessionEndCompleted)) {
995     IncrementPrefValue(prefs::kStabilityIncompleteSessionEndCount);
996     // This is marked false when we get a WM_ENDSESSION.
997     pref->SetBoolean(prefs::kStabilitySessionEndCompleted, true);
998   }
999
1000   // Initialize uptime counters.
1001   const base::TimeDelta startup_uptime = GetIncrementalUptime(pref);
1002   DCHECK_EQ(0, startup_uptime.InMicroseconds());
1003   // For backwards compatibility, leave this intact in case Omaha is checking
1004   // them.  prefs::kStabilityLastTimestampSec may also be useless now.
1005   // TODO(jar): Delete these if they have no uses.
1006   pref->SetInt64(prefs::kStabilityLaunchTimeSec, Time::Now().ToTimeT());
1007
1008   // Bookkeeping for the uninstall metrics.
1009   IncrementLongPrefsValue(prefs::kUninstallLaunchCount);
1010
1011   // Get stats on use of command line.
1012   const CommandLine* command_line(CommandLine::ForCurrentProcess());
1013   size_t common_commands = 0;
1014   if (command_line->HasSwitch(switches::kUserDataDir)) {
1015     ++common_commands;
1016     UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1);
1017   }
1018
1019   if (command_line->HasSwitch(switches::kApp)) {
1020     ++common_commands;
1021     UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1);
1022   }
1023
1024   size_t switch_count = command_line->GetSwitches().size();
1025   UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", switch_count);
1026   UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount",
1027                            switch_count - common_commands);
1028
1029   // Kick off the process of saving the state (so the uptime numbers keep
1030   // getting updated) every n minutes.
1031   ScheduleNextStateSave();
1032 }
1033
1034 // static
1035 void MetricsService::InitTaskGetHardwareClass(
1036     base::WeakPtr<MetricsService> self,
1037     base::MessageLoopProxy* target_loop) {
1038   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1039
1040   std::string hardware_class;
1041 #if defined(OS_CHROMEOS)
1042   chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
1043       "hardware_class", &hardware_class);
1044 #endif  // OS_CHROMEOS
1045
1046   target_loop->PostTask(FROM_HERE,
1047       base::Bind(&MetricsService::OnInitTaskGotHardwareClass,
1048           self, hardware_class));
1049 }
1050
1051 void MetricsService::OnInitTaskGotHardwareClass(
1052     const std::string& hardware_class) {
1053   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
1054   hardware_class_ = hardware_class;
1055
1056 #if defined(ENABLE_PLUGINS)
1057   // Start the next part of the init task: loading plugin information.
1058   PluginService::GetInstance()->GetPlugins(
1059       base::Bind(&MetricsService::OnInitTaskGotPluginInfo,
1060           self_ptr_factory_.GetWeakPtr()));
1061 #else
1062   std::vector<content::WebPluginInfo> plugin_list_empty;
1063   OnInitTaskGotPluginInfo(plugin_list_empty);
1064 #endif  // defined(ENABLE_PLUGINS)
1065 }
1066
1067 void MetricsService::OnInitTaskGotPluginInfo(
1068     const std::vector<content::WebPluginInfo>& plugins) {
1069   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
1070   plugins_ = plugins;
1071
1072   // Schedules a task on a blocking pool thread to gather Google Update
1073   // statistics (requires Registry reads).
1074   BrowserThread::PostBlockingPoolTask(
1075       FROM_HERE,
1076       base::Bind(&MetricsService::InitTaskGetGoogleUpdateData,
1077                  self_ptr_factory_.GetWeakPtr(),
1078                  base::MessageLoop::current()->message_loop_proxy()));
1079 }
1080
1081 // static
1082 void MetricsService::InitTaskGetGoogleUpdateData(
1083     base::WeakPtr<MetricsService> self,
1084     base::MessageLoopProxy* target_loop) {
1085   GoogleUpdateMetrics google_update_metrics;
1086
1087 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
1088   const bool system_install = GoogleUpdateSettings::IsSystemInstall();
1089
1090   google_update_metrics.is_system_install = system_install;
1091   google_update_metrics.last_started_au =
1092       GoogleUpdateSettings::GetGoogleUpdateLastStartedAU(system_install);
1093   google_update_metrics.last_checked =
1094       GoogleUpdateSettings::GetGoogleUpdateLastChecked(system_install);
1095   GoogleUpdateSettings::GetUpdateDetailForGoogleUpdate(
1096       system_install,
1097       &google_update_metrics.google_update_data);
1098   GoogleUpdateSettings::GetUpdateDetail(
1099       system_install,
1100       &google_update_metrics.product_data);
1101 #endif  // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
1102
1103   target_loop->PostTask(FROM_HERE,
1104       base::Bind(&MetricsService::OnInitTaskGotGoogleUpdateData,
1105           self, google_update_metrics));
1106 }
1107
1108 void MetricsService::OnInitTaskGotGoogleUpdateData(
1109     const GoogleUpdateMetrics& google_update_metrics) {
1110   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
1111
1112   google_update_metrics_ = google_update_metrics;
1113
1114   // Start the next part of the init task: fetching performance data.  This will
1115   // call into |FinishedReceivingProfilerData()| when the task completes.
1116   chrome_browser_metrics::TrackingSynchronizer::FetchProfilerDataAsynchronously(
1117       self_ptr_factory_.GetWeakPtr());
1118 }
1119
1120 void MetricsService::OnUserAction(const std::string& action) {
1121   if (!CanLogNotification())
1122     return;
1123
1124   log_manager_.current_log()->RecordUserAction(action.c_str());
1125   HandleIdleSinceLastTransmission(false);
1126 }
1127
1128 void MetricsService::ReceivedProfilerData(
1129     const tracked_objects::ProcessDataSnapshot& process_data,
1130     int process_type) {
1131   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
1132
1133   // Upon the first callback, create the initial log so that we can immediately
1134   // save the profiler data.
1135   if (!initial_metrics_log_.get())
1136     initial_metrics_log_.reset(new MetricsLog(client_id_, session_id_));
1137
1138   initial_metrics_log_->RecordProfilerData(process_data, process_type);
1139 }
1140
1141 void MetricsService::FinishedReceivingProfilerData() {
1142   DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
1143   state_ = INIT_TASK_DONE;
1144   scheduler_->InitTaskComplete();
1145 }
1146
1147 base::TimeDelta MetricsService::GetIncrementalUptime(PrefService* pref) {
1148   base::TimeTicks now = base::TimeTicks::Now();
1149   // If this is the first call, init |last_updated_time_|.
1150   if (last_updated_time_.is_null())
1151     last_updated_time_ = now;
1152   const base::TimeDelta incremental_time = now - last_updated_time_;
1153   last_updated_time_ = now;
1154
1155   const int64 incremental_time_secs = incremental_time.InSeconds();
1156   if (incremental_time_secs > 0) {
1157     int64 metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
1158     metrics_uptime += incremental_time_secs;
1159     pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
1160   }
1161
1162   return incremental_time;
1163 }
1164
1165 int MetricsService::GetLowEntropySource() {
1166   // Note that the default value for the low entropy source and the default pref
1167   // value are both kLowEntropySourceNotSet, which is used to identify if the
1168   // value has been set or not.
1169   if (low_entropy_source_ != kLowEntropySourceNotSet)
1170     return low_entropy_source_;
1171
1172   PrefService* local_state = g_browser_process->local_state();
1173   const CommandLine* command_line(CommandLine::ForCurrentProcess());
1174   // Only try to load the value from prefs if the user did not request a reset.
1175   // Otherwise, skip to generating a new value.
1176   if (!command_line->HasSwitch(switches::kResetVariationState)) {
1177     int value = local_state->GetInteger(prefs::kMetricsLowEntropySource);
1178     // Old versions of the code would generate values in the range of [1, 8192],
1179     // before the range was switched to [0, 8191] and then to [0, 7999]. Map
1180     // 8192 to 0, so that the 0th bucket remains uniform, while re-generating
1181     // the low entropy source for old values in the [8000, 8191] range.
1182     if (value == 8192)
1183       value = 0;
1184     // If the value is outside the [0, kMaxLowEntropySize) range, re-generate
1185     // it below.
1186     if (value >= 0 && value < kMaxLowEntropySize) {
1187       low_entropy_source_ = value;
1188       UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", false);
1189       return low_entropy_source_;
1190     }
1191   }
1192
1193   UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", true);
1194   low_entropy_source_ = GenerateLowEntropySource();
1195   local_state->SetInteger(prefs::kMetricsLowEntropySource, low_entropy_source_);
1196   metrics::CachingPermutedEntropyProvider::ClearCache(local_state);
1197
1198   return low_entropy_source_;
1199 }
1200
1201 // static
1202 std::string MetricsService::GenerateClientID() {
1203   return base::GenerateGUID();
1204 }
1205
1206 //------------------------------------------------------------------------------
1207 // State save methods
1208
1209 void MetricsService::ScheduleNextStateSave() {
1210   state_saver_factory_.InvalidateWeakPtrs();
1211
1212   base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
1213       base::Bind(&MetricsService::SaveLocalState,
1214                  state_saver_factory_.GetWeakPtr()),
1215       base::TimeDelta::FromMinutes(kSaveStateIntervalMinutes));
1216 }
1217
1218 void MetricsService::SaveLocalState() {
1219   PrefService* pref = g_browser_process->local_state();
1220   if (!pref) {
1221     NOTREACHED();
1222     return;
1223   }
1224
1225   RecordCurrentState(pref);
1226
1227   // TODO(jar):110021 Does this run down the batteries????
1228   ScheduleNextStateSave();
1229 }
1230
1231
1232 //------------------------------------------------------------------------------
1233 // Recording control methods
1234
1235 void MetricsService::OpenNewLog() {
1236   DCHECK(!log_manager_.current_log());
1237
1238   log_manager_.BeginLoggingWithLog(new MetricsLog(client_id_, session_id_),
1239                                    MetricsLog::ONGOING_LOG);
1240   if (state_ == INITIALIZED) {
1241     // We only need to schedule that run once.
1242     state_ = INIT_TASK_SCHEDULED;
1243
1244     // Schedules a task on the file thread for execution of slower
1245     // initialization steps (such as plugin list generation) necessary
1246     // for sending the initial log.  This avoids blocking the main UI
1247     // thread.
1248     BrowserThread::PostDelayedTask(
1249         BrowserThread::FILE,
1250         FROM_HERE,
1251         base::Bind(&MetricsService::InitTaskGetHardwareClass,
1252             self_ptr_factory_.GetWeakPtr(),
1253             base::MessageLoop::current()->message_loop_proxy()),
1254         base::TimeDelta::FromSeconds(kInitializationDelaySeconds));
1255   }
1256 }
1257
1258 void MetricsService::CloseCurrentLog() {
1259   if (!log_manager_.current_log())
1260     return;
1261
1262   // TODO(jar): Integrate bounds on log recording more consistently, so that we
1263   // can stop recording logs that are too big much sooner.
1264   if (log_manager_.current_log()->num_events() > kEventLimit) {
1265     UMA_HISTOGRAM_COUNTS("UMA.Discarded Log Events",
1266                          log_manager_.current_log()->num_events());
1267     log_manager_.DiscardCurrentLog();
1268     OpenNewLog();  // Start trivial log to hold our histograms.
1269   }
1270
1271   // Adds to ongoing logs.
1272   log_manager_.current_log()->set_hardware_class(hardware_class_);
1273
1274   // Put incremental data (histogram deltas, and realtime stats deltas) at the
1275   // end of all log transmissions (initial log handles this separately).
1276   // RecordIncrementalStabilityElements only exists on the derived
1277   // MetricsLog class.
1278   MetricsLog* current_log =
1279       static_cast<MetricsLog*>(log_manager_.current_log());
1280   DCHECK(current_log);
1281   std::vector<chrome_variations::ActiveGroupId> synthetic_trials;
1282   GetCurrentSyntheticFieldTrials(&synthetic_trials);
1283   current_log->RecordEnvironment(plugins_, google_update_metrics_,
1284                                  synthetic_trials);
1285   PrefService* pref = g_browser_process->local_state();
1286   current_log->RecordStabilityMetrics(GetIncrementalUptime(pref),
1287                                       MetricsLog::ONGOING_LOG);
1288
1289   RecordCurrentHistograms();
1290
1291   log_manager_.FinishCurrentLog();
1292 }
1293
1294 void MetricsService::PushPendingLogsToPersistentStorage() {
1295   if (state_ < SENDING_INITIAL_STABILITY_LOG)
1296     return;  // We didn't and still don't have time to get plugin list etc.
1297
1298   if (log_manager_.has_staged_log()) {
1299     // We may race here, and send second copy of the log later.
1300     MetricsLogManager::StoreType store_type;
1301     if (current_fetch_.get())
1302       store_type = MetricsLogManager::PROVISIONAL_STORE;
1303     else
1304       store_type = MetricsLogManager::NORMAL_STORE;
1305     log_manager_.StoreStagedLogAsUnsent(store_type);
1306   }
1307   DCHECK(!log_manager_.has_staged_log());
1308   CloseCurrentLog();
1309   log_manager_.PersistUnsentLogs();
1310
1311   // If there was a staged and/or current log, then there is now at least one
1312   // log waiting to be uploaded.
1313   if (log_manager_.has_unsent_logs())
1314     state_ = SENDING_OLD_LOGS;
1315 }
1316
1317 //------------------------------------------------------------------------------
1318 // Transmission of logs methods
1319
1320 void MetricsService::StartSchedulerIfNecessary() {
1321   // Never schedule cutting or uploading of logs in test mode.
1322   if (test_mode_active_)
1323     return;
1324
1325   // Even if reporting is disabled, the scheduler is needed to trigger the
1326   // creation of the initial log, which must be done in order for any logs to be
1327   // persisted on shutdown or backgrounding.
1328   if (recording_active() &&
1329       (reporting_active() || state_ < SENDING_INITIAL_STABILITY_LOG)) {
1330     scheduler_->Start();
1331   }
1332 }
1333
1334 void MetricsService::StartScheduledUpload() {
1335   // If we're getting no notifications, then the log won't have much in it, and
1336   // it's possible the computer is about to go to sleep, so don't upload and
1337   // stop the scheduler.
1338   // If recording has been turned off, the scheduler doesn't need to run.
1339   // If reporting is off, proceed if the initial log hasn't been created, since
1340   // that has to happen in order for logs to be cut and stored when persisting.
1341   // TODO(stuartmorgan): Call Stop() on the schedule when reporting and/or
1342   // recording are turned off instead of letting it fire and then aborting.
1343   if (idle_since_last_transmission_ ||
1344       !recording_active() ||
1345       (!reporting_active() && state_ >= SENDING_INITIAL_STABILITY_LOG)) {
1346     scheduler_->Stop();
1347     scheduler_->UploadCancelled();
1348     return;
1349   }
1350
1351   // If the callback was to upload an old log, but there no longer is one,
1352   // just report success back to the scheduler to begin the ongoing log
1353   // callbacks.
1354   // TODO(stuartmorgan): Consider removing the distinction between
1355   // SENDING_OLD_LOGS and SENDING_CURRENT_LOGS to simplify the state machine
1356   // now that the log upload flow is the same for both modes.
1357   if (state_ == SENDING_OLD_LOGS && !log_manager_.has_unsent_logs()) {
1358     state_ = SENDING_CURRENT_LOGS;
1359     scheduler_->UploadFinished(true /* healthy */, false /* no unsent logs */);
1360     return;
1361   }
1362   // If there are unsent logs, send the next one. If not, start the asynchronous
1363   // process of finalizing the current log for upload.
1364   if (state_ == SENDING_OLD_LOGS) {
1365     DCHECK(log_manager_.has_unsent_logs());
1366     log_manager_.StageNextLogForUpload();
1367     SendStagedLog();
1368   } else {
1369     StartFinalLogInfoCollection();
1370   }
1371 }
1372
1373 void MetricsService::StartFinalLogInfoCollection() {
1374   // Begin the multi-step process of collecting memory usage histograms:
1375   // First spawn a task to collect the memory details; when that task is
1376   // finished, it will call OnMemoryDetailCollectionDone. That will in turn
1377   // call HistogramSynchronization to collect histograms from all renderers and
1378   // then call OnHistogramSynchronizationDone to continue processing.
1379   DCHECK(!waiting_for_asynchronous_reporting_step_);
1380   waiting_for_asynchronous_reporting_step_ = true;
1381
1382   base::Closure callback =
1383       base::Bind(&MetricsService::OnMemoryDetailCollectionDone,
1384                  self_ptr_factory_.GetWeakPtr());
1385
1386   scoped_refptr<MetricsMemoryDetails> details(
1387       new MetricsMemoryDetails(callback));
1388   details->StartFetch(MemoryDetails::UPDATE_USER_METRICS);
1389
1390   // Collect WebCore cache information to put into a histogram.
1391   for (content::RenderProcessHost::iterator i(
1392           content::RenderProcessHost::AllHostsIterator());
1393        !i.IsAtEnd(); i.Advance())
1394     i.GetCurrentValue()->Send(new ChromeViewMsg_GetCacheResourceStats());
1395 }
1396
1397 void MetricsService::OnMemoryDetailCollectionDone() {
1398   DCHECK(IsSingleThreaded());
1399   // This function should only be called as the callback from an ansynchronous
1400   // step.
1401   DCHECK(waiting_for_asynchronous_reporting_step_);
1402
1403   // Create a callback_task for OnHistogramSynchronizationDone.
1404   base::Closure callback = base::Bind(
1405       &MetricsService::OnHistogramSynchronizationDone,
1406       self_ptr_factory_.GetWeakPtr());
1407
1408   base::TimeDelta timeout =
1409       base::TimeDelta::FromMilliseconds(kMaxHistogramGatheringWaitDuration);
1410
1411   DCHECK_EQ(num_async_histogram_fetches_in_progress_, 0);
1412
1413 #if defined(OS_ANDROID)
1414   // Android has no service process.
1415   num_async_histogram_fetches_in_progress_ = 1;
1416 #else  // OS_ANDROID
1417   num_async_histogram_fetches_in_progress_ = 2;
1418   // Run requests to service and content in parallel.
1419   if (!ServiceProcessControl::GetInstance()->GetHistograms(callback, timeout)) {
1420     // Assume |num_async_histogram_fetches_in_progress_| is not changed by
1421     // |GetHistograms()|.
1422     DCHECK_EQ(num_async_histogram_fetches_in_progress_, 2);
1423     // Assign |num_async_histogram_fetches_in_progress_| above and decrement it
1424     // here to make code work even if |GetHistograms()| fired |callback|.
1425     --num_async_histogram_fetches_in_progress_;
1426   }
1427 #endif  // OS_ANDROID
1428
1429   // Set up the callback to task to call after we receive histograms from all
1430   // child processes. Wait time specifies how long to wait before absolutely
1431   // calling us back on the task.
1432   content::FetchHistogramsAsynchronously(base::MessageLoop::current(), callback,
1433                                          timeout);
1434 }
1435
1436 void MetricsService::OnHistogramSynchronizationDone() {
1437   DCHECK(IsSingleThreaded());
1438   // This function should only be called as the callback from an ansynchronous
1439   // step.
1440   DCHECK(waiting_for_asynchronous_reporting_step_);
1441   DCHECK_GT(num_async_histogram_fetches_in_progress_, 0);
1442
1443   // Check if all expected requests finished.
1444   if (--num_async_histogram_fetches_in_progress_ > 0)
1445     return;
1446
1447   waiting_for_asynchronous_reporting_step_ = false;
1448   OnFinalLogInfoCollectionDone();
1449 }
1450
1451 void MetricsService::OnFinalLogInfoCollectionDone() {
1452   // If somehow there is a fetch in progress, we return and hope things work
1453   // out. The scheduler isn't informed since if this happens, the scheduler
1454   // will get a response from the upload.
1455   DCHECK(!current_fetch_.get());
1456   if (current_fetch_.get())
1457     return;
1458
1459   // Abort if metrics were turned off during the final info gathering.
1460   if (!recording_active()) {
1461     scheduler_->Stop();
1462     scheduler_->UploadCancelled();
1463     return;
1464   }
1465
1466   StageNewLog();
1467
1468   // If logs shouldn't be uploaded, stop here. It's important that this check
1469   // be after StageNewLog(), otherwise the previous logs will never be loaded,
1470   // and thus the open log won't be persisted.
1471   // TODO(stuartmorgan): This is unnecessarily complicated; restructure loading
1472   // of previous logs to not require running part of the upload logic.
1473   // http://crbug.com/157337
1474   if (!reporting_active()) {
1475     scheduler_->Stop();
1476     scheduler_->UploadCancelled();
1477     return;
1478   }
1479
1480   SendStagedLog();
1481 }
1482
1483 void MetricsService::StageNewLog() {
1484   if (log_manager_.has_staged_log())
1485     return;
1486
1487   switch (state_) {
1488     case INITIALIZED:
1489     case INIT_TASK_SCHEDULED:  // We should be further along by now.
1490       NOTREACHED();
1491       return;
1492
1493     case INIT_TASK_DONE:
1494       if (has_initial_stability_log_) {
1495         // There's an initial stability log, ready to send.
1496         log_manager_.StageNextLogForUpload();
1497         has_initial_stability_log_ = false;
1498         // Note: No need to call LoadPersistedUnsentLogs() here because unsent
1499         // logs have already been loaded by PrepareInitialStabilityLog().
1500         state_ = SENDING_INITIAL_STABILITY_LOG;
1501       } else {
1502         // TODO(asvitkine): When the field trial is removed, the |log_type|
1503         // arg should be removed and PrepareInitialMetricsLog() should always
1504         // use ONGOING_LOG. Use INITIAL_LOG only to match to the old behavior
1505         // when the field trial is off.
1506         MetricsLog::LogType log_type = SendSeparateInitialStabilityLog() ?
1507             MetricsLog::ONGOING_LOG : MetricsLog::INITIAL_LOG;
1508         PrepareInitialMetricsLog(log_type);
1509         // Load unsent logs (if any) from local state.
1510         log_manager_.LoadPersistedUnsentLogs();
1511         state_ = SENDING_INITIAL_METRICS_LOG;
1512       }
1513       break;
1514
1515     case SENDING_OLD_LOGS:
1516       NOTREACHED();  // Shouldn't be staging a new log during old log sending.
1517       return;
1518
1519     case SENDING_CURRENT_LOGS:
1520       CloseCurrentLog();
1521       OpenNewLog();
1522       log_manager_.StageNextLogForUpload();
1523       break;
1524
1525     default:
1526       NOTREACHED();
1527       return;
1528   }
1529
1530   DCHECK(log_manager_.has_staged_log());
1531 }
1532
1533 void MetricsService::PrepareInitialStabilityLog() {
1534   DCHECK_EQ(INITIALIZED, state_);
1535   PrefService* pref = g_browser_process->local_state();
1536   DCHECK_NE(0, pref->GetInteger(prefs::kStabilityCrashCount));
1537
1538   scoped_ptr<MetricsLog> initial_stability_log(
1539       new MetricsLog(client_id_, session_id_));
1540   if (!initial_stability_log->LoadSavedEnvironmentFromPrefs())
1541     return;
1542   initial_stability_log->RecordStabilityMetrics(base::TimeDelta(),
1543                                                 MetricsLog::INITIAL_LOG);
1544   log_manager_.LoadPersistedUnsentLogs();
1545
1546   log_manager_.PauseCurrentLog();
1547   log_manager_.BeginLoggingWithLog(initial_stability_log.release(),
1548                                    MetricsLog::INITIAL_LOG);
1549 #if defined(OS_ANDROID)
1550   ConvertAndroidStabilityPrefsToHistograms(pref);
1551   RecordCurrentStabilityHistograms();
1552 #endif  // defined(OS_ANDROID)
1553   log_manager_.FinishCurrentLog();
1554   log_manager_.ResumePausedLog();
1555
1556   // Store unsent logs, including the stability log that was just saved, so
1557   // that they're not lost in case of a crash before upload time.
1558   log_manager_.PersistUnsentLogs();
1559
1560   has_initial_stability_log_ = true;
1561 }
1562
1563 void MetricsService::PrepareInitialMetricsLog(MetricsLog::LogType log_type) {
1564   DCHECK(state_ == INIT_TASK_DONE || state_ == SENDING_INITIAL_STABILITY_LOG);
1565   initial_metrics_log_->set_hardware_class(hardware_class_);
1566
1567   std::vector<chrome_variations::ActiveGroupId> synthetic_trials;
1568   GetCurrentSyntheticFieldTrials(&synthetic_trials);
1569   initial_metrics_log_->RecordEnvironment(plugins_, google_update_metrics_,
1570                                           synthetic_trials);
1571   PrefService* pref = g_browser_process->local_state();
1572   initial_metrics_log_->RecordStabilityMetrics(GetIncrementalUptime(pref),
1573                                                log_type);
1574
1575   // Histograms only get written to the current log, so make the new log current
1576   // before writing them.
1577   log_manager_.PauseCurrentLog();
1578   log_manager_.BeginLoggingWithLog(initial_metrics_log_.release(), log_type);
1579 #if defined(OS_ANDROID)
1580   ConvertAndroidStabilityPrefsToHistograms(pref);
1581 #endif  // defined(OS_ANDROID)
1582   RecordCurrentHistograms();
1583   log_manager_.FinishCurrentLog();
1584   log_manager_.ResumePausedLog();
1585
1586   DCHECK(!log_manager_.has_staged_log());
1587   log_manager_.StageNextLogForUpload();
1588 }
1589
1590 void MetricsService::SendStagedLog() {
1591   DCHECK(log_manager_.has_staged_log());
1592
1593   PrepareFetchWithStagedLog();
1594
1595   bool upload_created = (current_fetch_.get() != NULL);
1596   UMA_HISTOGRAM_BOOLEAN("UMA.UploadCreation", upload_created);
1597   if (!upload_created) {
1598     // Compression failed, and log discarded :-/.
1599     // Skip this upload and hope things work out next time.
1600     log_manager_.DiscardStagedLog();
1601     scheduler_->UploadCancelled();
1602     return;
1603   }
1604
1605   DCHECK(!waiting_for_asynchronous_reporting_step_);
1606   waiting_for_asynchronous_reporting_step_ = true;
1607
1608   current_fetch_->Start();
1609
1610   HandleIdleSinceLastTransmission(true);
1611 }
1612
1613 void MetricsService::PrepareFetchWithStagedLog() {
1614   DCHECK(log_manager_.has_staged_log());
1615
1616   // Prepare the protobuf version.
1617   DCHECK(!current_fetch_.get());
1618   if (log_manager_.has_staged_log()) {
1619     current_fetch_.reset(net::URLFetcher::Create(
1620         GURL(kServerUrl), net::URLFetcher::POST, this));
1621     current_fetch_->SetRequestContext(
1622         g_browser_process->system_request_context());
1623
1624     std::string log_text = log_manager_.staged_log_text();
1625     std::string compressed_log_text;
1626     bool compression_successful = chrome::GzipCompress(log_text,
1627                                                        &compressed_log_text);
1628     DCHECK(compression_successful);
1629     if (compression_successful) {
1630       current_fetch_->SetUploadData(kMimeType, compressed_log_text);
1631       // Tell the server that we're uploading gzipped protobufs.
1632       current_fetch_->SetExtraRequestHeaders("content-encoding: gzip");
1633       const std::string hash =
1634           base::HexEncode(log_manager_.staged_log_hash().data(),
1635                           log_manager_.staged_log_hash().size());
1636       DCHECK(!hash.empty());
1637       current_fetch_->AddExtraRequestHeader("X-Chrome-UMA-Log-SHA1: " + hash);
1638       UMA_HISTOGRAM_PERCENTAGE(
1639           "UMA.ProtoCompressionRatio",
1640           100 * compressed_log_text.size() / log_text.size());
1641       UMA_HISTOGRAM_CUSTOM_COUNTS(
1642           "UMA.ProtoGzippedKBSaved",
1643           (log_text.size() - compressed_log_text.size()) / 1024,
1644           1, 2000, 50);
1645     }
1646
1647     // We already drop cookies server-side, but we might as well strip them out
1648     // client-side as well.
1649     current_fetch_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
1650                                  net::LOAD_DO_NOT_SEND_COOKIES);
1651   }
1652 }
1653
1654 void MetricsService::OnURLFetchComplete(const net::URLFetcher* source) {
1655   DCHECK(waiting_for_asynchronous_reporting_step_);
1656
1657   // We're not allowed to re-use the existing |URLFetcher|s, so free them here.
1658   // Note however that |source| is aliased to the fetcher, so we should be
1659   // careful not to delete it too early.
1660   DCHECK_EQ(current_fetch_.get(), source);
1661   scoped_ptr<net::URLFetcher> s(current_fetch_.Pass());
1662
1663   int response_code = source->GetResponseCode();
1664
1665   // Log a histogram to track response success vs. failure rates.
1666   UMA_HISTOGRAM_ENUMERATION("UMA.UploadResponseStatus.Protobuf",
1667                             ResponseCodeToStatus(response_code),
1668                             NUM_RESPONSE_STATUSES);
1669
1670   // If the upload was provisionally stored, drop it now that the upload is
1671   // known to have gone through.
1672   log_manager_.DiscardLastProvisionalStore();
1673
1674   bool upload_succeeded = response_code == 200;
1675
1676   // Provide boolean for error recovery (allow us to ignore response_code).
1677   bool discard_log = false;
1678   const size_t log_size = log_manager_.staged_log_text().length();
1679   if (!upload_succeeded && log_size > kUploadLogAvoidRetransmitSize) {
1680     UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded",
1681                          static_cast<int>(log_size));
1682     discard_log = true;
1683   } else if (response_code == 400) {
1684     // Bad syntax.  Retransmission won't work.
1685     discard_log = true;
1686   }
1687
1688   if (upload_succeeded || discard_log)
1689     log_manager_.DiscardStagedLog();
1690
1691   waiting_for_asynchronous_reporting_step_ = false;
1692
1693   if (!log_manager_.has_staged_log()) {
1694     switch (state_) {
1695       case SENDING_INITIAL_STABILITY_LOG:
1696         // Store the updated list to disk now that the removed log is uploaded.
1697         log_manager_.PersistUnsentLogs();
1698         PrepareInitialMetricsLog(MetricsLog::ONGOING_LOG);
1699         SendStagedLog();
1700         state_ = SENDING_INITIAL_METRICS_LOG;
1701         break;
1702
1703       case SENDING_INITIAL_METRICS_LOG:
1704         // The initial metrics log never gets persisted to local state, so it's
1705         // not necessary to call log_manager_.PersistUnsentLogs() here.
1706         // TODO(asvitkine): It should be persisted like the initial stability
1707         // log and old unsent logs. http://crbug.com/328417
1708         state_ = log_manager_.has_unsent_logs() ? SENDING_OLD_LOGS
1709                                                 : SENDING_CURRENT_LOGS;
1710         break;
1711
1712       case SENDING_OLD_LOGS:
1713         // Store the updated list to disk now that the removed log is uploaded.
1714         log_manager_.PersistUnsentLogs();
1715         if (!log_manager_.has_unsent_logs())
1716           state_ = SENDING_CURRENT_LOGS;
1717         break;
1718
1719       case SENDING_CURRENT_LOGS:
1720         break;
1721
1722       default:
1723         NOTREACHED();
1724         break;
1725     }
1726
1727     if (log_manager_.has_unsent_logs())
1728       DCHECK_LT(state_, SENDING_CURRENT_LOGS);
1729   }
1730
1731   // Error 400 indicates a problem with the log, not with the server, so
1732   // don't consider that a sign that the server is in trouble.
1733   bool server_is_healthy = upload_succeeded || response_code == 400;
1734   // Don't notify the scheduler that the upload is finished if we've only sent
1735   // the initial stability log, but not yet the initial metrics log (treat the
1736   // two as a single unit of work as far as the scheduler is concerned).
1737   if (state_ != SENDING_INITIAL_METRICS_LOG) {
1738     scheduler_->UploadFinished(server_is_healthy,
1739                                log_manager_.has_unsent_logs());
1740   }
1741
1742   // Collect network stats if UMA upload succeeded.
1743   IOThread* io_thread = g_browser_process->io_thread();
1744   if (server_is_healthy && io_thread) {
1745     chrome_browser_net::CollectNetworkStats(network_stats_server_, io_thread);
1746     chrome_browser_net::CollectPipeliningCapabilityStatsOnUIThread(
1747         http_pipelining_test_server_, io_thread);
1748 #if defined(OS_WIN)
1749     chrome::CollectTimeTicksStats();
1750 #endif
1751   }
1752 }
1753
1754 void MetricsService::IncrementPrefValue(const char* path) {
1755   PrefService* pref = g_browser_process->local_state();
1756   DCHECK(pref);
1757   int value = pref->GetInteger(path);
1758   pref->SetInteger(path, value + 1);
1759 }
1760
1761 void MetricsService::IncrementLongPrefsValue(const char* path) {
1762   PrefService* pref = g_browser_process->local_state();
1763   DCHECK(pref);
1764   int64 value = pref->GetInt64(path);
1765   pref->SetInt64(path, value + 1);
1766 }
1767
1768 void MetricsService::LogLoadStarted(content::WebContents* web_contents) {
1769   content::RecordAction(base::UserMetricsAction("PageLoad"));
1770   HISTOGRAM_ENUMERATION("Chrome.UmaPageloadCounter", 1, 2);
1771   IncrementPrefValue(prefs::kStabilityPageLoadCount);
1772   IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount);
1773   // We need to save the prefs, as page load count is a critical stat, and it
1774   // might be lost due to a crash :-(.
1775 }
1776
1777 void MetricsService::LogRendererCrash(content::RenderProcessHost* host,
1778                                       base::TerminationStatus status,
1779                                       int exit_code) {
1780   bool was_extension_process =
1781       extensions::ProcessMap::Get(host->GetBrowserContext())
1782           ->Contains(host->GetID());
1783   if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
1784       status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
1785     if (was_extension_process) {
1786       IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount);
1787
1788       UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Extension",
1789                                   MapCrashExitCodeForHistogram(exit_code));
1790     } else {
1791       IncrementPrefValue(prefs::kStabilityRendererCrashCount);
1792
1793       UMA_HISTOGRAM_SPARSE_SLOWLY("CrashExitCodes.Renderer",
1794                                   MapCrashExitCodeForHistogram(exit_code));
1795     }
1796
1797     UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
1798                              was_extension_process ? 2 : 1);
1799   } else if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
1800     UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
1801                              was_extension_process ? 2 : 1);
1802   } else if (status == base::TERMINATION_STATUS_STILL_RUNNING) {
1803     UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.DisconnectedAlive",
1804                                was_extension_process ? 2 : 1);
1805   }
1806 }
1807
1808 void MetricsService::LogRendererHang() {
1809   IncrementPrefValue(prefs::kStabilityRendererHangCount);
1810 }
1811
1812 bool MetricsService::UmaMetricsProperlyShutdown() {
1813   CHECK(clean_shutdown_status_ == CLEANLY_SHUTDOWN ||
1814         clean_shutdown_status_ == NEED_TO_SHUTDOWN);
1815   return clean_shutdown_status_ == CLEANLY_SHUTDOWN;
1816 }
1817
1818 void MetricsService::RegisterSyntheticFieldTrial(
1819     const SyntheticTrialGroup& trial) {
1820   for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
1821     if (synthetic_trial_groups_[i].id.name == trial.id.name) {
1822       if (synthetic_trial_groups_[i].id.group != trial.id.group) {
1823         synthetic_trial_groups_[i].id.group = trial.id.group;
1824         synthetic_trial_groups_[i].start_time = trial.start_time;
1825       }
1826       return;
1827     }
1828   }
1829
1830   SyntheticTrialGroup trial_group(
1831       trial.id.name, trial.id.group, base::TimeTicks::Now());
1832   synthetic_trial_groups_.push_back(trial_group);
1833 }
1834
1835 void MetricsService::GetCurrentSyntheticFieldTrials(
1836     std::vector<chrome_variations::ActiveGroupId>* synthetic_trials) {
1837   DCHECK(synthetic_trials);
1838   synthetic_trials->clear();
1839   const MetricsLog* current_log =
1840       static_cast<const MetricsLog*>(log_manager_.current_log());
1841   for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) {
1842     if (synthetic_trial_groups_[i].start_time <= current_log->creation_time())
1843       synthetic_trials->push_back(synthetic_trial_groups_[i].id);
1844   }
1845 }
1846
1847 void MetricsService::LogCleanShutdown() {
1848   // Redundant hack to write pref ASAP.
1849   MarkAppCleanShutdownAndCommit();
1850
1851   // Redundant setting to assure that we always reset this value at shutdown
1852   // (and that we don't use some alternate path, and not call LogCleanShutdown).
1853   clean_shutdown_status_ = CLEANLY_SHUTDOWN;
1854
1855   RecordBooleanPrefValue(prefs::kStabilityExitedCleanly, true);
1856   PrefService* pref = g_browser_process->local_state();
1857   pref->SetInteger(prefs::kStabilityExecutionPhase,
1858                    MetricsService::SHUTDOWN_COMPLETE);
1859 }
1860
1861 #if defined(OS_CHROMEOS)
1862 void MetricsService::LogChromeOSCrash(const std::string &crash_type) {
1863   if (crash_type == "user")
1864     IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
1865   else if (crash_type == "kernel")
1866     IncrementPrefValue(prefs::kStabilityKernelCrashCount);
1867   else if (crash_type == "uncleanshutdown")
1868     IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
1869   else
1870     NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type;
1871   // Wake up metrics logs sending if necessary now that new
1872   // log data is available.
1873   HandleIdleSinceLastTransmission(false);
1874 }
1875 #endif  // OS_CHROMEOS
1876
1877 void MetricsService::LogPluginLoadingError(const base::FilePath& plugin_path) {
1878   content::WebPluginInfo plugin;
1879   bool success =
1880       content::PluginService::GetInstance()->GetPluginInfoByPath(plugin_path,
1881                                                                  &plugin);
1882   DCHECK(success);
1883   ChildProcessStats& stats = child_process_stats_buffer_[plugin.name];
1884   // Initialize the type if this entry is new.
1885   if (stats.process_type == content::PROCESS_TYPE_UNKNOWN) {
1886     // The plug-in process might not actually of type PLUGIN (which means
1887     // NPAPI), but we only care that it is *a* plug-in process.
1888     stats.process_type = content::PROCESS_TYPE_PLUGIN;
1889   } else {
1890     DCHECK(IsPluginProcess(stats.process_type));
1891   }
1892   stats.loading_errors++;
1893 }
1894
1895 MetricsService::ChildProcessStats& MetricsService::GetChildProcessStats(
1896     const content::ChildProcessData& data) {
1897   const base::string16& child_name = data.name;
1898   if (!ContainsKey(child_process_stats_buffer_, child_name)) {
1899     child_process_stats_buffer_[child_name] =
1900         ChildProcessStats(data.process_type);
1901   }
1902   return child_process_stats_buffer_[child_name];
1903 }
1904
1905 void MetricsService::RecordPluginChanges(PrefService* pref) {
1906   ListPrefUpdate update(pref, prefs::kStabilityPluginStats);
1907   base::ListValue* plugins = update.Get();
1908   DCHECK(plugins);
1909
1910   for (base::ListValue::iterator value_iter = plugins->begin();
1911        value_iter != plugins->end(); ++value_iter) {
1912     if (!(*value_iter)->IsType(base::Value::TYPE_DICTIONARY)) {
1913       NOTREACHED();
1914       continue;
1915     }
1916
1917     base::DictionaryValue* plugin_dict =
1918         static_cast<base::DictionaryValue*>(*value_iter);
1919     std::string plugin_name;
1920     plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name);
1921     if (plugin_name.empty()) {
1922       NOTREACHED();
1923       continue;
1924     }
1925
1926     // TODO(viettrungluu): remove conversions
1927     base::string16 name16 = base::UTF8ToUTF16(plugin_name);
1928     if (child_process_stats_buffer_.find(name16) ==
1929         child_process_stats_buffer_.end()) {
1930       continue;
1931     }
1932
1933     ChildProcessStats stats = child_process_stats_buffer_[name16];
1934     if (stats.process_launches) {
1935       int launches = 0;
1936       plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
1937       launches += stats.process_launches;
1938       plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, launches);
1939     }
1940     if (stats.process_crashes) {
1941       int crashes = 0;
1942       plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
1943       crashes += stats.process_crashes;
1944       plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, crashes);
1945     }
1946     if (stats.instances) {
1947       int instances = 0;
1948       plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
1949       instances += stats.instances;
1950       plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances);
1951     }
1952     if (stats.loading_errors) {
1953       int loading_errors = 0;
1954       plugin_dict->GetInteger(prefs::kStabilityPluginLoadingErrors,
1955                               &loading_errors);
1956       loading_errors += stats.loading_errors;
1957       plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors,
1958                               loading_errors);
1959     }
1960
1961     child_process_stats_buffer_.erase(name16);
1962   }
1963
1964   // Now go through and add dictionaries for plugins that didn't already have
1965   // reports in Local State.
1966   for (std::map<base::string16, ChildProcessStats>::iterator cache_iter =
1967            child_process_stats_buffer_.begin();
1968        cache_iter != child_process_stats_buffer_.end(); ++cache_iter) {
1969     ChildProcessStats stats = cache_iter->second;
1970
1971     // Insert only plugins information into the plugins list.
1972     if (!IsPluginProcess(stats.process_type))
1973       continue;
1974
1975     // TODO(viettrungluu): remove conversion
1976     std::string plugin_name = base::UTF16ToUTF8(cache_iter->first);
1977
1978     base::DictionaryValue* plugin_dict = new base::DictionaryValue;
1979
1980     plugin_dict->SetString(prefs::kStabilityPluginName, plugin_name);
1981     plugin_dict->SetInteger(prefs::kStabilityPluginLaunches,
1982                             stats.process_launches);
1983     plugin_dict->SetInteger(prefs::kStabilityPluginCrashes,
1984                             stats.process_crashes);
1985     plugin_dict->SetInteger(prefs::kStabilityPluginInstances,
1986                             stats.instances);
1987     plugin_dict->SetInteger(prefs::kStabilityPluginLoadingErrors,
1988                             stats.loading_errors);
1989     plugins->Append(plugin_dict);
1990   }
1991   child_process_stats_buffer_.clear();
1992 }
1993
1994 bool MetricsService::CanLogNotification() {
1995   // We simply don't log anything to UMA if there is a single incognito
1996   // session visible. The problem is that we always notify using the orginal
1997   // profile in order to simplify notification processing.
1998   return !chrome::IsOffTheRecordSessionActive();
1999 }
2000
2001 void MetricsService::RecordBooleanPrefValue(const char* path, bool value) {
2002   DCHECK(IsSingleThreaded());
2003
2004   PrefService* pref = g_browser_process->local_state();
2005   DCHECK(pref);
2006
2007   pref->SetBoolean(path, value);
2008   RecordCurrentState(pref);
2009 }
2010
2011 void MetricsService::RecordCurrentState(PrefService* pref) {
2012   pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT());
2013
2014   RecordPluginChanges(pref);
2015 }
2016
2017 // static
2018 bool MetricsService::IsPluginProcess(int process_type) {
2019   return (process_type == content::PROCESS_TYPE_PLUGIN ||
2020           process_type == content::PROCESS_TYPE_PPAPI_PLUGIN ||
2021           process_type == content::PROCESS_TYPE_PPAPI_BROKER);
2022 }
2023
2024 #if defined(OS_CHROMEOS)
2025 void MetricsService::StartExternalMetrics() {
2026   external_metrics_ = new chromeos::ExternalMetrics;
2027   external_metrics_->Start();
2028 }
2029 #endif
2030
2031 // static
2032 bool MetricsServiceHelper::IsMetricsReportingEnabled() {
2033   bool result = false;
2034   const PrefService* local_state = g_browser_process->local_state();
2035   if (local_state) {
2036     const PrefService::Preference* uma_pref =
2037         local_state->FindPreference(prefs::kMetricsReportingEnabled);
2038     if (uma_pref) {
2039       bool success = uma_pref->GetValue()->GetAsBoolean(&result);
2040       DCHECK(success);
2041     }
2042   }
2043   return result;
2044 }