172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Description of the life cycle of a instance of MetricsService. 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// OVERVIEW 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A MetricsService instance is typically created at application startup. It 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is the central controller for the acquisition of log data, and the automatic 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// transmission of that log data to an external server. Its major job is to 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// manage logs, grouping them for transmission, and transmitting them. As part 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of its grouping, MS finalizes logs by including some just-in-time gathered 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// memory statistics, snapshotting the current stats of numerous histograms, 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// closing the logs, translating to XML text, and compressing the results for 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// transmission. Transmission includes submitting a compressed log as data in a 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// URL-post, and retransmitting (or retaining at process termination) if the 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// attempted transmission failed. Retention across process terminations is done 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// using the the PrefServices facilities. The retained logs (the ones that never 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// got transmitted) are compressed and base64-encoded before being persisted. 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Logs fall into one of two categories: "initial logs," and "ongoing logs." 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There is at most one initial log sent for each complete run of the chromium 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// product (from startup, to browser shutdown). An initial log is generally 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// transmitted some short time (1 minute?) after startup, and includes stats 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// such as recent crash info, the number and types of plugins, etc. The 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// external server's response to the initial log conceptually tells this MS if 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// it should continue transmitting logs (during this session). The server 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// response can actually be much more detailed, and always includes (at a 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// minimum) how often additional ongoing logs should be sent. 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// After the above initial log, a series of ongoing logs will be transmitted. 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The first ongoing log actually begins to accumulate information stating when 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the MS was first constructed. Note that even though the initial log is 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// commonly sent a full minute after startup, the initial log does not include 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// much in the way of user stats. The most common interlog period (delay) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is 20 minutes. That time period starts when the first user action causes a 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// logging event. This means that if there is no user action, there may be long 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// periods without any (ongoing) log transmissions. Ongoing logs typically 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// contain very detailed records of user activities (ex: opened tab, closed 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// tab, fetched URL, maximized window, etc.) In addition, just before an 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ongoing log is closed out, a call is made to gather memory statistics. Those 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// memory statistics are deposited into a histogram, and the log finalization 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// code is then called. In the finalization, a call to a Histogram server 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// acquires a list of all local histograms that have been flagged for upload 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// to the UMA server. The finalization also acquires a the most recent number 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of page loads, along with any counts of renderer or plugin crashes. 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When the browser shuts down, there will typically be a fragment of an ongoing 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// log that has not yet been transmitted. At shutdown time, that fragment 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is closed (including snapshotting histograms), and converted to text. Note 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that memory stats are not gathered during shutdown, as gathering *might* be 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// too time consuming. The textual representation of the fragment of the 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ongoing log is then stored persistently as a string in the PrefServices, for 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// potential transmission during a future run of the product. 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// There are two slightly abnormal shutdown conditions. There is a 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// "disconnected scenario," and a "really fast startup and shutdown" scenario. 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the "never connected" situation, the user has (during the running of the 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// process) never established an internet connection. As a result, attempts to 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// transmit the initial log have failed, and a lot(?) of data has accumulated in 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the ongoing log (which didn't yet get closed, because there was never even a 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// contemplation of sending it). There is also a kindred "lost connection" 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// situation, where a loss of connection prevented an ongoing log from being 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// transmitted, and a (still open) log was stuck accumulating a lot(?) of data, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// while the earlier log retried its transmission. In both of these 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// disconnected situations, two logs need to be, and are, persistently stored 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// for future transmission. 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The other unusual shutdown condition, termed "really fast startup and 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// shutdown," involves the deliberate user termination of the process before 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the initial log is even formed or transmitted. In that situation, no logging 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// is done, but the historical crash statistics remain (unlogged) for inclusion 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// in a future run's initial log. (i.e., we don't lose crash stats). 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// With the above overview, we can now describe the state machine's various 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// stats, based on the State enum specified in the state_ member. Those states 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// are: 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INITIALIZED, // Constructor was called. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to complete. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INIT_TASK_DONE, // Waiting for timer to send initial log. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INITIAL_LOG_READY, // Initial log generated, and waiting for reply. 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SEND_OLD_INITIAL_LOGS, // Sending unsent logs from previous session. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SENDING_OLD_LOGS, // Sending unsent logs from previous session. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SENDING_CURRENT_LOGS, // Sending standard current logs as they accrue. 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In more detail, we have: 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INITIALIZED, // Constructor was called. 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The MS has been constructed, but has taken no actions to compose the 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// initial log. 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INIT_TASK_SCHEDULED, // Waiting for deferred init tasks to complete. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Typically about 30 seconds after startup, a task is sent to a second thread 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (the file thread) to perform deferred (lower priority and slower) 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// initialization steps such as getting the list of plugins. That task will 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (when complete) make an async callback (via a Task) to indicate the 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// completion. 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INIT_TASK_DONE, // Waiting for timer to send initial log. 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The callback has arrived, and it is now possible for an initial log to be 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// created. This callback typically arrives back less than one second after 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the deferred init task is dispatched. 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// INITIAL_LOG_READY, // Initial log generated, and waiting for reply. 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This state is entered only after an initial log has been composed, and 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// prepared for transmission. It is also the case that any previously unsent 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// logs have been loaded into instance variables for possible transmission. 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SEND_OLD_INITIAL_LOGS, // Sending unsent logs from previous session. 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This state indicates that the initial log for this session has been 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// successfully sent and it is now time to send any "initial logs" that were 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// saved from previous sessions. Most commonly, there are none, but all old 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// logs that were "initial logs" must be sent before this state is exited. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SENDING_OLD_LOGS, // Sending unsent logs from previous session. 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This state indicates that there are no more unsent initial logs, and now any 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ongoing logs from previous sessions should be transmitted. All such logs 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will be transmitted before exiting this state, and proceeding with ongoing 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// logs from the current session (see next state). 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SENDING_CURRENT_LOGS, // Sending standard current logs as they accrue. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Current logs are being accumulated. Typically every 20 minutes a log is 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// closed and finalized for transmission, at the same time as a new log is 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// started. 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The progression through the above states is simple, and sequential, in the 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// most common use cases. States proceed from INITIAL to SENDING_CURRENT_LOGS, 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and remain in the latter until shutdown. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The one unusual case is when the user asks that we stop logging. When that 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// happens, any pending (transmission in progress) log is pushed into the list 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// of old unsent logs (the appropriate list, depending on whether it is an 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// initial log, or an ongoing log). An addition, any log that is currently 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// accumulating is also finalized, and pushed into the unsent log list. With 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// those pushes performed, we regress back to the SEND_OLD_INITIAL_LOGS state in 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// case the user enables log recording again during this session. This way 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// anything we have "pushed back" will be sent automatically if/when we progress 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// back to SENDING_CURRENT_LOG state. 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Also note that whenever the member variables containing unsent logs are 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// modified (i.e., when we send an old log), we mirror the list of logs into 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the PrefServices. This ensures that IF we crash, we won't start up and 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// retransmit our old logs again. 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Due to race conditions, it is always possible that a log file could be sent 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// twice. For example, if a log file is sent, but not yet acknowledged by 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the external server, and the user shuts down, then a copy of the log may be 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// saved for re-transmission. These duplicates could be filtered out server 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// side, but are not expected to be a significant problem. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/metrics_service.h" 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h" 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/command_line.h" 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/md5.h" 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 1643f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/threading/thread.h" 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h" 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/load_notification_details.h" 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/memory_details.h" 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/histogram_synchronizer.h" 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/metrics_log.h" 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h" 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/prefs/scoped_user_pref_update.h" 17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url_model.h" 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h" 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/child_process_logging.h" 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/common/guid.h" 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/render_messages.h" 184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_process_host.h" 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/child_process_info.h" 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "libxml/xmlwriter.h" 18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/plugins/npapi/plugin_list.h" 18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "webkit/plugins/npapi/webplugininfo.h" 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(port): port browser_distribution.h. 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(OS_POSIX) 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/installer/util/browser_distribution.h" 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS) 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/chromeos/cros/cros_library.h" 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/external_metrics.h" 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/system_access.h" 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMetricsService::LogRecallStatus MakeRecallStatusHistogram( 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsService::LogRecallStatus status) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogRecall", status, 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsService::END_RECALL_STATUS); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return status; 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(ziadh): Remove this when done with experiment. 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MakeStoreStatusHistogram(MetricsService::LogStoreStatus status) { 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UMA_HISTOGRAM_ENUMERATION("PrefService.PersistentLogStore2", status, 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsService::END_STORE_STATUS); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Check to see that we're being called on only one thread. 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool IsSingleThreaded(); 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kMetricsType[] = "application/vnd.mozilla.metrics.bz2"; 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The delay, in seconds, after startup before sending the first log message. 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kInitialInterlogDuration = 60; // one minute 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This specifies the amount of time to wait for all renderers to send their 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// data. 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxHistogramGatheringWaitDuration = 60000; // 60 seconds. 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// The maximum number of events in a log uploaded to the UMA server. 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kEventLimit = 2400; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// If an upload fails, and the transmission was over this byte count, then we 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// will discard the log, and not try to retransmit it. We also don't persist 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the log to the prefs for transmission during the next chrome session if this 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// limit is exceeded. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kUploadLogAvoidRetransmitSize = 50000; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When we have logs from previous Chrome sessions to send, how long should we 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// delay (in seconds) between each log transmission. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kUnsentLogDelay = 15; // 15 seconds 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Minimum time a log typically exists before sending, in seconds. 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This number is supplied by the server, but until we parse it out of a server 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// response, we use this duration to specify how long we should wait before 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sending the next log. If the channel is busy, such as when there is a 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// failure during an attempt to transmit a previous log, then a log may wait 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// (and continue to accrue new log entries) for a much greater period of time. 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMinSecondsPerLog = 30 * 60; // Thirty minutes. 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When we don't succeed at transmitting a log to a server, we progressively 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// wait longer and longer before sending the next log. This backoff process 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// help reduce load on the server, and makes the amount of backoff vary between 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// clients so that a collision (server overload?) on retransmit is less likely. 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The following is the constant we use to expand that inter-log duration. 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const double kBackoff = 1.1; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We limit the maximum backoff to be no greater than some multiple of the 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// default kMinSecondsPerLog. The following is that maximum ratio. 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxBackoff = 10; 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Interval, in seconds, between state saves. 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSaveStateInterval = 5 * 60; // five minutes 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of "initial" logs we're willing to save, and hope to send during 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a future Chrome session. Initial logs contain crash stats, and are pretty 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// small. 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const size_t kMaxInitialLogsPersisted = 20; 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of ongoing logs we're willing to save persistently, and hope to 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// send during a this or future sessions. Note that each log may be pretty 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// large, as presumably the related "initial" log wasn't sent (probably nothing 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// was, as the user was probably off-line). As a result, the log probably kept 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// accumulating while the "initial" log was stalled (pending_), and couldn't be 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sent. As a result, we don't want to save too many of these mega-logs. 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A "standard shutdown" will create a small log, including just the data that 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// was not yet been transmitted, and that is normal (to have exactly one 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ongoing_log_ at startup). 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const size_t kMaxOngoingLogsPersisted = 8; 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We append (2) more elements to persisted lists: the size of the list and a 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// checksum of the elements. 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const size_t kChecksumEntryCount = 2; 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is used to quickly log stats from child process related notifications in 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// MetricsService::child_stats_buffer_. The buffer's contents are transferred 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// out when Local State is periodically saved. The information is then 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// reported to the UMA server on next launch. 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct MetricsService::ChildProcessStats { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit ChildProcessStats(ChildProcessInfo::ProcessType type) 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : process_launches(0), 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_crashes(0), 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instances(0), 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_type(type) {} 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This constructor is only used by the map to return some default value for 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // an index for which no value has been assigned. 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildProcessStats() 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : process_launches(0), 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_crashes(0), 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instances(0), 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_type(ChildProcessInfo::UNKNOWN_PROCESS) {} 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number of times that the given child process has been launched 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int process_launches; 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number of times that the given child process has crashed 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int process_crashes; 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The number of instances of this child process that have been created. 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // An instance is a DOM object rendered by this child process during a page 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // load. 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int instances; 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildProcessInfo::ProcessType process_type; 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Handles asynchronous fetching of memory details. 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Will run the provided task after finished. 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MetricsMemoryDetails : public MemoryDetails { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit MetricsMemoryDetails(Task* completion) : completion_(completion) {} 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnDetailsAvailable() { 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostTask(FROM_HERE, completion_); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~MetricsMemoryDetails() {} 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Task* completion_; 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetails); 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MetricsService::InitTaskComplete : public Task { 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit InitTaskComplete( 34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& hardware_class, 34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::vector<webkit::npapi::WebPluginInfo>& plugins) 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : hardware_class_(hardware_class), plugins_(plugins) {} 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process->metrics_service()->OnInitTaskComplete( 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hardware_class_, plugins_); 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string hardware_class_; 35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<webkit::npapi::WebPluginInfo> plugins_; 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass MetricsService::InitTask : public Task { 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit InitTask(MessageLoop* callback_loop) 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : callback_loop_(callback_loop) {} 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() { 36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen std::vector<webkit::npapi::WebPluginInfo> plugins; 36121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen webkit::npapi::PluginList::Singleton()->GetPlugins(false, &plugins); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string hardware_class; // Empty string by default. 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS) 364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chromeos::SystemAccess::GetInstance()->GetMachineStatistic( 365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "hardware_class", &hardware_class); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // OS_CHROMEOS 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_loop_->PostTask(FROM_HERE, new InitTaskComplete( 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hardware_class, plugins)); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop* callback_loop_; 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RegisterPrefs(PrefService* local_state) { 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterStringPref(prefs::kMetricsClientID, ""); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kMetricsClientIDTimestamp, 0); 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kStabilityLaunchTimeSec, 0); 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kStabilityLastTimestampSec, 0); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterStringPref(prefs::kStabilityStatsVersion, ""); 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kStabilityStatsBuildTime, 0); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterBooleanPref(prefs::kStabilityExitedCleanly, true); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterBooleanPref(prefs::kStabilitySessionEndCompleted, true); 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kMetricsSessionID, -1); 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityLaunchCount, 0); 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityCrashCount, 0); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityIncompleteSessionEndCount, 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityPageLoadCount, 0); 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityRendererCrashCount, 0); 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityExtensionRendererCrashCount, 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityRendererHangCount, 0); 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityChildProcessCrashCount, 0); 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationFail, 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityBreakpadRegistrationSuccess, 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityDebuggerPresent, 0); 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kStabilityDebuggerNotPresent, 0); 40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_CHROMEOS) 40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_state->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0); 40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_state->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0); 40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen local_state->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount, 40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 0); 40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif // OS_CHROMEOS 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterDictionaryPref(prefs::kProfileMetrics); 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kNumBookmarksOnBookmarkBar, 0); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kNumFoldersOnBookmarkBar, 0); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kNumBookmarksInOtherBookmarkFolder, 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0); 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kNumFoldersInOtherBookmarkFolder, 0); 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kNumKeywords, 0); 417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterListPref(prefs::kMetricsInitialLogs); 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterListPref(prefs::kMetricsOngoingLogs); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallMetricsPageLoadCount, 0); 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallLaunchCount, 0); 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallMetricsInstallDate, 0); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallMetricsUptimeSec, 0); 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0); 425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0); 426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::DiscardOldStabilityStats(PrefService* local_state) { 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetBoolean(prefs::kStabilityExitedCleanly, true); 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetBoolean(prefs::kStabilitySessionEndCompleted, true); 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0); 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0); 435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0); 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityDebuggerPresent, 0); 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityDebuggerNotPresent, 0); 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityLaunchCount, 0); 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityCrashCount, 0); 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityPageLoadCount, 0); 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityRendererCrashCount, 0); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInteger(prefs::kStabilityRendererHangCount, 0); 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInt64(prefs::kStabilityLaunchTimeSec, 0); 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->SetInt64(prefs::kStabilityLastTimestampSec, 0); 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->ClearPref(prefs::kStabilityPluginStats); 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen local_state->ClearPref(prefs::kMetricsInitialLogs); 452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen local_state->ClearPref(prefs::kMetricsOngoingLogs); 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMetricsService::MetricsService() 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : recording_active_(false), 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reporting_active_(false), 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_permits_upload_(true), 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_(INITIALIZED), 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_(NULL), 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch idle_since_last_transmission_(false), 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_window_id_(0), 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(log_sender_factory_(this)), 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(state_saver_factory_(this)), 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_(TimeDelta::FromSeconds(kInitialInterlogDuration)), 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_(false) { 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitializeMetricsState(); 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMetricsService::~MetricsService() { 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetRecording(false); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::Start() { 476ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HandleIdleSinceLastTransmission(false); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetRecording(true); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetReporting(true); 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StartRecordingOnly() { 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetRecording(true); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetReporting(false); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::Stop() { 487ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HandleIdleSinceLastTransmission(false); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetReporting(false); 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetRecording(false); 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::SetRecording(bool enabled) { 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (enabled == recording_active_) 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (enabled) { 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (client_id_.empty()) { 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_id_ = pref->GetString(prefs::kMetricsClientID); 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (client_id_.empty()) { 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client_id_ = GenerateClientID(); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetString(prefs::kMetricsClientID, client_id_); 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Might as well make a note of how long this ID has existed 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetString(prefs::kMetricsClientIDTimestamp, 5093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Int64ToString(Time::Now().ToTimeT())); 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_logging::SetClientId(client_id_); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartRecording(); 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetUpNotifications(®istrar_, this); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_.RemoveAll(); 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PushPendingLogsToUnsentLists(); 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!pending_log()); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ > INITIAL_LOG_READY && unsent_logs()) 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = SEND_OLD_INITIAL_LOGS; 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch recording_active_ = enabled; 524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MetricsService::recording_active() const { 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return recording_active_; 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::SetReporting(bool enable) { 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (reporting_active_ != enable) { 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reporting_active_ = enable; 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (reporting_active_) 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MetricsService::reporting_active() const { 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reporting_active_; 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 545ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid MetricsService::SetUpNotifications(NotificationRegistrar* registrar, 546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationObserver* observer) { 547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::BROWSER_OPENED, 548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::BROWSER_CLOSED, 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::USER_ACTION, 552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::TAB_PARENTED, 554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::TAB_CLOSING, 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::LOAD_START, 558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::LOAD_STOP, 560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::RENDERER_PROCESS_CLOSED, 562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::RENDERER_PROCESS_HANG, 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::CHILD_PROCESS_HOST_CONNECTED, 566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::CHILD_INSTANCE_CREATED, 568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::CHILD_PROCESS_CRASHED, 570dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::TEMPLATE_URL_MODEL_LOADED, 572dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::OMNIBOX_OPENED_URL, 574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar->Add(observer, NotificationType::BOOKMARK_MODEL_LOADED, 576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NotificationService::AllSources()); 577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::Observe(NotificationType type, 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(current_log_); 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!CanLogNotification(type, source, details)) 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::USER_ACTION: 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->RecordUserAction(*Details<const char*>(details).ptr()); 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_OPENED: 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_CLOSED: 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogWindowChange(type, source, details); 596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_PARENTED: 599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_CLOSING: 600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogWindowChange(type, source, details); 601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::LOAD_STOP: 604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogLoadComplete(type, source, details); 605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::LOAD_START: 608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogLoadStarted(); 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen case NotificationType::RENDERER_PROCESS_CLOSED: { 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RenderProcessHost::RendererClosedDetails* process_details = 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<RenderProcessHost::RendererClosedDetails>(details).ptr(); 61421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (process_details->status == 61521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TERMINATION_STATUS_PROCESS_CRASHED || 61621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen process_details->status == 61721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TERMINATION_STATUS_ABNORMAL_TERMINATION) { 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (process_details->was_extension_renderer) { 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogExtensionRendererCrash(); 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogRendererCrash(); 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::RENDERER_PROCESS_HANG: 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogRendererHang(); 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_PROCESS_HOST_CONNECTED: 632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_PROCESS_CRASHED: 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_INSTANCE_CREATED: 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogChildProcessChange(type, source, details); 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TEMPLATE_URL_MODEL_LOADED: 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogKeywords(Source<TemplateURLModel>(source).ptr()); 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::OMNIBOX_OPENED_URL: { 642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLog* current_log = current_log_->AsMetricsLog(); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(current_log); 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log->RecordOmniboxOpenedURL( 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *Details<AutocompleteLog>(details).ptr()); 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BOOKMARK_MODEL_LOADED: { 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Profile* p = Source<Profile>(source).ptr(); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (p) 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogBookmarks(p->GetBookmarkModel()); 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 6563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleIdleSinceLastTransmission(false); 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_log_) 663731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "METRICS: NUMBER OF EVENTS = " << current_log_->num_events(); 664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::HandleIdleSinceLastTransmission(bool in_idle) { 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there wasn't a lot of action, maybe the computer was asleep, in which 668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case, the log transmissions should have stopped. Here we start them up 669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // again. 670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!in_idle && idle_since_last_transmission_) 671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); 672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch idle_since_last_transmission_ = in_idle; 673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecordStartOfSessionEnd() { 676ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LogCleanShutdown(); 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, false); 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecordCompletedSessionEnd() { 681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LogCleanShutdown(); 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordBooleanPrefValue(prefs::kStabilitySessionEndCompleted, true); 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService:: RecordBreakpadRegistration(bool success) { 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!success) 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityBreakpadRegistrationFail); 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityBreakpadRegistrationSuccess); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecordBreakpadHasDebugger(bool has_debugger) { 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!has_debugger) 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityDebuggerNotPresent); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityDebuggerPresent); 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// private methods 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Initialization methods 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::InitializeMetricsState() { 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_POSIX) 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_url_ = L"https://clients4.google.com/firefox/metrics/collect"; 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_url_ = dist->GetStatsServerURL(); 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((pref->GetInt64(prefs::kStabilityStatsBuildTime) 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch != MetricsLog::GetBuildTime()) || 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (pref->GetString(prefs::kStabilityStatsVersion) 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch != MetricsLog::GetVersionString())) { 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is a new version, so we don't want to confuse the stats about the 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // old version with info that we upload. 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardOldStabilityStats(pref); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetString(prefs::kStabilityStatsVersion, 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLog::GetVersionString()); 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInt64(prefs::kStabilityStatsBuildTime, 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLog::GetBuildTime()); 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update session ID 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session_id_ = pref->GetInteger(prefs::kMetricsSessionID); 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++session_id_; 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInteger(prefs::kMetricsSessionID, session_id_); 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stability bookkeeping 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityLaunchCount); 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pref->GetBoolean(prefs::kStabilityExitedCleanly)) { 740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityCrashCount); 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This will be set to 'true' if we exit cleanly. 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetBoolean(prefs::kStabilityExitedCleanly, false); 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pref->GetBoolean(prefs::kStabilitySessionEndCompleted)) { 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityIncompleteSessionEndCount); 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is marked false when we get a WM_ENDSESSION. 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetBoolean(prefs::kStabilitySessionEndCompleted, true); 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initialize uptime counters. 753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 startup_uptime = MetricsLog::GetIncrementalUptime(pref); 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0, startup_uptime); 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For backwards compatibility, leave this intact in case Omaha is checking 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them. prefs::kStabilityLastTimestampSec may also be useless now. 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): Delete these if they have no uses. 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInt64(prefs::kStabilityLaunchTimeSec, Time::Now().ToTimeT()); 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bookkeeping for the uninstall metrics. 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementLongPrefsValue(prefs::kUninstallLaunchCount); 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Save profile metrics. 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = g_browser_process->local_state(); 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prefs) { 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remove the current dictionary and store it for use when sending data to 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // server. By removing the value we prune potentially dead profiles 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (and keys). All valid values are added back once services startup. 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue* profile_dictionary = 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->GetDictionary(prefs::kProfileMetrics); 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (profile_dictionary) { 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do a deep copy of profile_dictionary since ClearPref will delete it. 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_dictionary_.reset(static_cast<DictionaryValue*>( 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_dictionary->DeepCopy())); 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->ClearPref(prefs::kProfileMetrics); 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get stats on use of command line. 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const CommandLine* command_line(CommandLine::ForCurrentProcess()); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t common_commands = 0; 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command_line->HasSwitch(switches::kUserDataDir)) { 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++common_commands; 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineDatDirCount", 1); 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (command_line->HasSwitch(switches::kApp)) { 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++common_commands; 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineAppModeCount", 1); 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineFlagCount", 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command_line->GetSwitchCount()); 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Chrome.CommandLineUncommonFlagCount", 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch command_line->GetSwitchCount() - common_commands); 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Kick off the process of saving the state (so the uptime numbers keep 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // getting updated) every n minutes. 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleNextStateSave(); 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::OnInitTaskComplete( 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& hardware_class, 80421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::vector<webkit::npapi::WebPluginInfo>& plugins) { 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ == INIT_TASK_SCHEDULED); 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hardware_class_ = hardware_class; 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugins_ = plugins; 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == INIT_TASK_SCHEDULED) 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = INIT_TASK_DONE; 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string MetricsService::GenerateClientID() { 813731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return guid::GenerateGUID(); 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// State save methods 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::ScheduleNextStateSave() { 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_saver_factory_.RevokeAll(); 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_saver_factory_.NewRunnableMethod(&MetricsService::SaveLocalState), 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kSaveStateInterval * 1000); 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::SaveLocalState() { 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pref) { 8303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordCurrentState(pref); 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->ScheduleSavePersistentPrefs(); 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): Does this run down the batteries???? 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleNextStateSave(); 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Recording control methods 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StartRecording() { 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_log_) 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_ = new MetricsLog(client_id_, session_id_); 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == INITIALIZED) { 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only need to schedule that run once. 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = INIT_TASK_SCHEDULED; 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Schedules a task on the file thread for execution of slower 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // initialization steps (such as plugin list generation) necessary 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // for sending the initial log. This avoids blocking the main UI 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thread. 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process->file_thread()->message_loop()->PostDelayedTask(FROM_HERE, 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new InitTask(MessageLoop::current()), 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kInitialInterlogDuration * 1000 / 2); 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StopRecording(MetricsLogBase** log) { 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_log_) 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_log_->set_hardware_class(hardware_class_); // Adds to ongoing logs. 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): Integrate bounds on log recording more consistently, so that we 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // can stop recording logs that are too big much sooner. 872ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (current_log_->num_events() > kEventLimit) { 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("UMA.Discarded Log Events", 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->num_events()); 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->CloseLog(); 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete current_log_; 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_ = NULL; 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartRecording(); // Start trivial log to hold our histograms. 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Put incremental data (histogram deltas, and realtime stats deltas) at the 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // end of all log transmissions (initial log handles this separately). 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't bother if we're going to discard current_log_. 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (log) { 88572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // RecordIncrementalStabilityElements only exists on the derived 88672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // MetricsLog class. 88772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MetricsLog* current_log = current_log_->AsMetricsLog(); 88872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(current_log); 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log->RecordIncrementalStabilityElements(); 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordCurrentHistograms(); 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->CloseLog(); 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (log) 89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *log = current_log_; 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete current_log_; 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_ = NULL; 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::PushPendingLogsToUnsentLists() { 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ < INITIAL_LOG_READY) 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // We didn't and still don't have time to get plugin list etc. 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pending_log()) { 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PreparePendingLogText(); 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ == INITIAL_LOG_READY) { 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We may race here, and send second copy of initial log later. 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unsent_initial_logs_.push_back(compressed_log_); 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = SEND_OLD_INITIAL_LOGS; 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): Verify correctness in other states, including sending unsent 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // initial logs. 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PushPendingLogTextToUnsentOngoingLogs(); 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardPendingLog(); 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!pending_log()); 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopRecording(&pending_log_); 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PreparePendingLogText(); 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PushPendingLogTextToUnsentOngoingLogs(); 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardPendingLog(); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StoreUnsentLogs(); 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::PushPendingLogTextToUnsentOngoingLogs() { 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If UMA response told us not to upload, there's no need to save the pending 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // log. It wasn't supposed to be uploaded anyway. 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!server_permits_upload_) 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (compressed_log_.length() > 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<size_t>(kUploadLogAvoidRetransmitSize)) { 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("UMA.Large Accumulated Log Not Persisted", 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(compressed_log_.length())); 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unsent_ongoing_logs_.push_back(compressed_log_); 938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//------------------------------------------------------------------------------ 941c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Transmission of logs methods 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StartLogTransmissionTimer() { 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're not reporting, there's no point in starting a log transmission 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // timer. 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!reporting_active()) 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_log_) 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Recorder is shutdown. 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If there is already a timer running, we leave it running. 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If timer_pending is true because the fetch is waiting for a response, 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we return for now and let the response handler start the timer. 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (timer_pending_) 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Before starting the timer, set timer_pending_ to true. 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_ = true; 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Right before the UMA transmission gets started, there's one more thing we'd 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // like to record: the histogram of memory usage, so we spawn a task to 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // collect the memory details and when that task is finished, it will call 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnMemoryDetailCollectionDone, which will call HistogramSynchronization to 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // collect histograms from all renderers and then we will call 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnHistogramSynchronizationDone to continue processing. 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch log_sender_factory_. 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(&MetricsService::LogTransmissionTimerDone), 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_.InMilliseconds()); 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogTransmissionTimerDone() { 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Task* task = log_sender_factory_. 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(&MetricsService::OnMemoryDetailCollectionDone); 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 977513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch scoped_refptr<MetricsMemoryDetails> details(new MetricsMemoryDetails(task)); 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch details->StartFetch(); 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Collect WebCore cache information to put into a histogram. 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !i.IsAtEnd(); i.Advance()) 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i.GetCurrentValue()->Send(new ViewMsg_GetCacheResourceStats()); 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::OnMemoryDetailCollectionDone() { 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // HistogramSynchronizer will Collect histograms from all renderers and it 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // will call OnHistogramSynchronizationDone (if wait time elapses before it 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // heard from all renderers, then also it will call 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OnHistogramSynchronizationDone). 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create a callback_task for OnHistogramSynchronizationDone. 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Task* callback_task = log_sender_factory_.NewRunnableMethod( 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &MetricsService::OnHistogramSynchronizationDone); 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set up the callback to task to call after we receive histograms from all 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // renderer processes. Wait time specifies how long to wait before absolutely 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // calling us back on the task. 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HistogramSynchronizer::FetchRendererHistogramsAsynchronously( 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current(), callback_task, 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kMaxHistogramGatheringWaitDuration); 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::OnHistogramSynchronizationDone() { 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This function should only be called via timer, so timer_pending_ 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should be true. 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(timer_pending_); 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_ = false; 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!current_fetch_.get()); 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we're getting no notifications, then the log won't have much in it, and 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // it's possible the computer is about to go to sleep, so don't upload and 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // don't restart the transmission timer. 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (idle_since_last_transmission_) 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If somehow there is a fetch in progress, we return setting timer_pending_ 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to true and hope things work out. 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (current_fetch_.get()) { 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_ = true; 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If uploads are forbidden by UMA response, there's no point in keeping 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the current_log_, and the more often we delete it, the less likely it is 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to expand forever. 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!server_permits_upload_ && current_log_) { 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopRecording(NULL); 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartRecording(); 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_log_) 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Logging was disabled. 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!reporting_active()) 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Don't do work if we're not going to send anything now. 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MakePendingLog(); 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MakePendingLog should have put something in the pending log, if it didn't, 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we start the timer again, return and hope things work out. 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pending_log()) { 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1051ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If we're not supposed to upload any UMA data because the response said so, 1052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // cancel the upload at this point, but start the timer. 1053ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!ServerPermitsTransmission()) { 1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardPendingLog(); 1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); 1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareFetchWithPendingLog(); 1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1061c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!current_fetch_.get()) { 1062c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compression failed, and log discarded :-/. 1063c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardPendingLog(); 1064c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); // Maybe we'll do better next time 1065c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): If compression failed, we should have created a tiny log and 1066c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // compressed that, so that we can signal that we're losing logs. 1067c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1068c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1069c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1070c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!timer_pending_); 1071c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1072c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The URL fetch is a like timer in that after a while we get called back 1073c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we set timer_pending_ true just as we start the url fetch. 1074c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_ = true; 1075c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_->Start(); 1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleIdleSinceLastTransmission(true); 1078c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::MakePendingLog() { 1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pending_log()) 1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INITIALIZED: 1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INIT_TASK_SCHEDULED: // We should be further along by now. 1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false); 1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INIT_TASK_DONE: 1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to wait for the initial log to be ready before sending 1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // anything, because the server will tell us whether it wants to hear 1094c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // from us. 1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrepareInitialLog(); 1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ == INIT_TASK_DONE); 1097c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecallUnsentLogs(); 1098c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = INITIAL_LOG_READY; 1099c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SEND_OLD_INITIAL_LOGS: 1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!unsent_initial_logs_.empty()) { 1103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressed_log_ = unsent_initial_logs_.back(); 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = SENDING_OLD_LOGS; 1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fall through. 1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_OLD_LOGS: 1110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!unsent_ongoing_logs_.empty()) { 1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressed_log_ = unsent_ongoing_logs_.back(); 1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = SENDING_CURRENT_LOGS; 1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Fall through. 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_CURRENT_LOGS: 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopRecording(&pending_log_); 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartRecording(); 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 11233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pending_log()); 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool MetricsService::ServerPermitsTransmission() const { 1131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If the server forbids uploading, we take that to mean it forbids current 1132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // logs, but we still send up the inital logs and any old logs. 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (server_permits_upload_) 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INITIAL_LOG_READY: 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SEND_OLD_INITIAL_LOGS: 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_OLD_LOGS: 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_CURRENT_LOGS: 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::PrepareInitialLog() { 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ == INIT_TASK_DONE); 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLog* log = new MetricsLog(client_id_, session_id_); 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch log->set_hardware_class(hardware_class_); // Adds to initial log. 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch log->RecordEnvironment(plugins_, profile_dictionary_.get()); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Histograms only get written to current_log_, so setup for the write. 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLogBase* save_log = current_log_; 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_ = log; 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordCurrentHistograms(); // Into current_log_... which is really log. 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_ = save_log; 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch log->CloseLog(); 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!pending_log()); 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_log_ = log; 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMetricsService::LogRecallStatus MetricsService::RecallUnsentLogsHelper( 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ListValue& list, 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<std::string>* local_list) { 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_list->empty()); 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (list.GetSize() == 0) 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(LIST_EMPTY); 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (list.GetSize() < 3) 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(LIST_SIZE_TOO_SMALL); 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The size is stored at the beginning of the list. 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int size; 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool valid = (*list.begin())->GetAsInteger(&size); 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!valid) 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(LIST_SIZE_MISSING); 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Account for checksum and size included in the list. 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (static_cast<unsigned int>(size) != 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list.GetSize() - kChecksumEntryCount) 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(LIST_SIZE_CORRUPTION); 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Context ctx; 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Init(&ctx); 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string encoded_log; 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string decoded_log; 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::const_iterator it = list.begin() + 1; 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != list.end() - 1; ++it) { // Last element is the checksum. 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid = (*it)->GetAsString(&encoded_log); 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!valid) { 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_list->clear(); 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(LOG_STRING_CORRUPTION); 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Update(&ctx, encoded_log.data(), encoded_log.length()); 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!base::Base64Decode(encoded_log, &decoded_log)) { 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_list->clear(); 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(DECODE_FAIL); 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_list->push_back(decoded_log); 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Verify checksum. 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Digest digest; 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Final(&digest, &ctx); 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string recovered_md5; 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We store the hash at the end of the list. 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch valid = (*(list.end() - 1))->GetAsString(&recovered_md5); 1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!valid) { 1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_list->clear(); 1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(CHECKSUM_STRING_CORRUPTION); 1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (recovered_md5 != MD5DigestToBase16(digest)) { 1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_list->clear(); 1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(CHECKSUM_CORRUPTION); 1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeRecallStatusHistogram(RECALL_SUCCESS); 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecallUnsentLogs() { 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state = g_browser_process->local_state(); 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_state); 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ListValue* unsent_initial_logs = local_state->GetList( 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kMetricsInitialLogs); 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecallUnsentLogsHelper(*unsent_initial_logs, &unsent_initial_logs_); 1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ListValue* unsent_ongoing_logs = local_state->GetList( 1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kMetricsOngoingLogs); 1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecallUnsentLogsHelper(*unsent_ongoing_logs, &unsent_ongoing_logs_); 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StoreUnsentLogsHelper( 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::vector<std::string>& local_list, 1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const size_t kMaxLocalListSize, 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* list) { 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->Clear(); 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t start = 0; 1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_list.size() > kMaxLocalListSize) 1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch start = local_list.size() - kMaxLocalListSize; 1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(start <= local_list.size()); 1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_list.size() == start) 1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Store size at the beginning of the list. 1251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->Append(Value::CreateIntegerValue(local_list.size() - start)); 1252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Context ctx; 1254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Init(&ctx); 1255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string encoded_log; 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::vector<std::string>::const_iterator it = local_list.begin() + start; 1257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != local_list.end(); ++it) { 1258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We encode the compressed log as Value::CreateStringValue() expects to 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // take a valid UTF8 string. 1260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!base::Base64Encode(*it, &encoded_log)) { 1261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MakeStoreStatusHistogram(ENCODE_FAIL); 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->Clear(); 1263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Update(&ctx, encoded_log.data(), encoded_log.length()); 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->Append(Value::CreateStringValue(encoded_log)); 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Append hash to the end of the list. 1270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Digest digest; 1271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Final(&digest, &ctx); 1272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch list->Append(Value::CreateStringValue(MD5DigestToBase16(digest))); 1273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(list->GetSize() >= 3); // Minimum of 3 elements (size, data, hash). 12743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick MakeStoreStatusHistogram(STORE_SUCCESS); 1275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StoreUnsentLogs() { 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (state_ < INITIAL_LOG_READY) 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // We never Recalled the prior unsent logs. 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state = g_browser_process->local_state(); 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_state); 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 1285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListPrefUpdate update(local_state, prefs::kMetricsInitialLogs); 1286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* unsent_initial_logs = update.Get(); 1287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StoreUnsentLogsHelper(unsent_initial_logs_, kMaxInitialLogsPersisted, 1288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unsent_initial_logs); 1289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 1292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListPrefUpdate update(local_state, prefs::kMetricsOngoingLogs); 1293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* unsent_ongoing_logs = update.Get(); 1294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StoreUnsentLogsHelper(unsent_ongoing_logs_, kMaxOngoingLogsPersisted, 1295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unsent_ongoing_logs); 1296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::PreparePendingLogText() { 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pending_log()); 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!compressed_log_.empty()) 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int text_size = pending_log_->GetEncodedLogSize(); 1304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string pending_log_text; 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Leave room for the NULL terminator. 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pending_log_->GetEncodedLog(WriteInto(&pending_log_text, text_size + 1), 1308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch text_size); 1309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (Bzip2Compress(pending_log_text, &compressed_log_)) { 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Allow security conscious users to see all metrics logs that we send. 1312731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "COMPRESSED FOLLOWING METRICS LOG: " << pending_log_text; 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(DFATAL) << "Failed to compress log for transmission."; 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't discard the logs as other caller functions expect that 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |compressed_log_| not be empty. We can detect this failure at the server 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // after we transmit. 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressed_log_ = "Unable to compress!"; 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MakeStoreStatusHistogram(COMPRESS_FAIL); 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::PrepareFetchWithPendingLog() { 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pending_log()); 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!current_fetch_.get()); 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PreparePendingLogText(); 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!compressed_log_.empty()); 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_.reset(new URLFetcher(GURL(WideToUTF16(server_url_)), 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLFetcher::POST, 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this)); 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_->set_request_context(Profile::GetDefaultRequestContext()); 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_->set_upload_data(kMetricsType, compressed_log_); 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const char* StatusToString(const net::URLRequestStatus& status) { 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (status.status()) { 133972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case net::URLRequestStatus::SUCCESS: 1340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "SUCCESS"; 1341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case net::URLRequestStatus::IO_PENDING: 1343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "IO_PENDING"; 1344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case net::URLRequestStatus::HANDLED_EXTERNALLY: 1346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "HANDLED_EXTERNALLY"; 1347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case net::URLRequestStatus::CANCELED: 1349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "CANCELED"; 1350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case net::URLRequestStatus::FAILED: 1352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "FAILED"; 1353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 13553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return "Unknown"; 1357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::OnURLFetchComplete(const URLFetcher* source, 1361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 136272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const net::URLRequestStatus& status, 1363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 1364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 1365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data) { 1366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(timer_pending_); 1367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch timer_pending_ = false; 1368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(current_fetch_.get()); 1369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_fetch_.reset(NULL); // We're not allowed to re-use it. 1370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Confirm send so that we can move on. 1372731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "METRICS RESPONSE CODE: " << response_code 1373731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " status=" << StatusToString(status); 1374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Provide boolean for error recovery (allow us to ignore response_code). 1376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool discard_log = false; 1377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (response_code != 200 && 1379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (compressed_log_.length() > 1380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<size_t>(kUploadLogAvoidRetransmitSize))) { 1381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("UMA.Large Rejected Log was Discarded", 1382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(compressed_log_.length())); 1383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_log = true; 1384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (response_code == 400) { 1385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bad syntax. Retransmission won't work. 1386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("UMA.Unacceptable_Log_Discarded", state_); 1387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch discard_log = true; 1388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (response_code != 200 && !discard_log) { 1391731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "METRICS: transmission attempt returned a failure code: " 1392731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << response_code << ". Verify network connectivity"; 1393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HandleBadResponseCode(); 1394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { // Successful receipt (or we are discarding log). 1395731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "METRICS RESPONSE DATA: " << data; 1396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 1397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case INITIAL_LOG_READY: 1398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = SEND_OLD_INITIAL_LOGS; 1399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SEND_OLD_INITIAL_LOGS: 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!unsent_initial_logs_.empty()); 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unsent_initial_logs_.pop_back(); 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StoreUnsentLogs(); 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_OLD_LOGS: 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!unsent_ongoing_logs_.empty()); 1409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch unsent_ongoing_logs_.pop_back(); 1410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StoreUnsentLogs(); 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SENDING_CURRENT_LOGS: 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 14173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DiscardPendingLog(); 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Since we sent a log, make sure our in-memory state is recorded to disk. 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* local_state = g_browser_process->local_state(); 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(local_state); 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (local_state) 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->ScheduleSavePersistentPrefs(); 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Override usual interlog delay if there are unsent logs to transmit, 1429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // otherwise reset back to default. 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (unsent_logs()) { 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(state_ < SENDING_CURRENT_LOGS); 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_ = TimeDelta::FromSeconds(kUnsentLogDelay); 1433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen interlog_duration_ = TimeDelta::FromSeconds(kMinSecondsPerLog); 1435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartLogTransmissionTimer(); 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::HandleBadResponseCode() { 1442731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Verify your metrics logs are formatted correctly. Verify server " 1443731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick "is active at " << server_url_; 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pending_log()) { 1445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "METRICS: Recorder shutdown during log transmission."; 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Send progressively less frequently. 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(kBackoff > 1.0); 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_ = TimeDelta::FromMicroseconds( 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int64>(kBackoff * interlog_duration_.InMicroseconds())); 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (kMaxBackoff * TimeDelta::FromSeconds(kMinSecondsPerLog) < 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_) { 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch interlog_duration_ = kMaxBackoff * 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromSeconds(kMinSecondsPerLog); 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1458731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "METRICS: transmission retry being scheduled in " 1459731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << interlog_duration_.InSeconds() << " seconds for " 1460731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << compressed_log_; 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogWindowChange(NotificationType type, 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int controller_id = -1; 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uintptr_t window_or_tab = source.map_key(); 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsLog::WindowEventType window_type; 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: since we stop all logging when a single OTR session is active, it is 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // possible that we start getting notifications about a window that we don't 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // know about. 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (window_map_.find(window_or_tab) == window_map_.end()) { 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_id = next_window_id_++; 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_map_[window_or_tab] = controller_id; 1477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller_id = window_map_[window_or_tab]; 1479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(controller_id, -1); 1481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 1483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_PARENTED: 1484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_OPENED: 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_type = MetricsLog::WINDOW_CREATE; 1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::TAB_CLOSING: 1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::BROWSER_CLOSED: 1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_map_.erase(window_map_.find(window_or_tab)); 1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch window_type = MetricsLog::WINDOW_DESTROY; 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 14953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(brettw) we should have some kind of ID for the parent. 1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->RecordWindowEvent(window_type, controller_id, 0); 1501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogLoadComplete(NotificationType type, 1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (details == NotificationService::NoDetails()) 1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(jar): There is a bug causing this to be called too many times, and 1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the log overflows. For now, we won't record these events. 1511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("UMA.LogLoadComplete called", 1); 1512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const Details<LoadNotificationDetails> load_details(details); 1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int controller_id = window_map_[details.map_key()]; 1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_log_->RecordLoadEvent(controller_id, 1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch load_details->url(), 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch load_details->origin(), 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch load_details->session_index(), 1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch load_details->load_time()); 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MetricsService::IncrementPrefValue(const char* path) { 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int value = pref->GetInteger(path); 1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInteger(path, value + 1); 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MetricsService::IncrementLongPrefsValue(const char* path) { 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 value = pref->GetInt64(path); 1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInt64(path, value + 1); 1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogLoadStarted() { 1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityPageLoadCount); 1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementLongPrefsValue(prefs::kUninstallMetricsPageLoadCount); 1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to save the prefs, as page load count is a critical stat, and it 1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // might be lost due to a crash :-(. 1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogRendererCrash() { 1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityRendererCrashCount); 1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogExtensionRendererCrash() { 1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityExtensionRendererCrashCount); 1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogRendererHang() { 1553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityRendererHangCount); 1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1556ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid MetricsService::LogCleanShutdown() { 1557ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RecordBooleanPrefValue(prefs::kStabilityExitedCleanly, true); 1558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 156072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_CHROMEOS) 156172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MetricsService::LogChromeOSCrash(const std::string &crash_type) { 156272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (crash_type == "user") 156372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen IncrementPrefValue(prefs::kStabilityOtherUserCrashCount); 156472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (crash_type == "kernel") 156572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen IncrementPrefValue(prefs::kStabilityKernelCrashCount); 156672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else if (crash_type == "uncleanshutdown") 156772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount); 156872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 156972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type; 157072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Wake up metrics logs sending if necessary now that new 157172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // log data is available. 157272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HandleIdleSinceLastTransmission(false); 157372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 157472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif // OS_CHROMEOS 157572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogChildProcessChange( 1577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NotificationType type, 1578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Details<ChildProcessInfo> child_details(details); 1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::wstring& child_name = child_details->name(); 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (child_process_stats_buffer_.find(child_name) == 1584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_stats_buffer_.end()) { 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_stats_buffer_[child_name] = 1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildProcessStats(child_details->type()); 1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildProcessStats& stats = child_process_stats_buffer_[child_name]; 1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (type.value) { 1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_PROCESS_HOST_CONNECTED: 1592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.process_launches++; 1593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_INSTANCE_CREATED: 1596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.instances++; 1597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case NotificationType::CHILD_PROCESS_CRASHED: 1600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.process_crashes++; 1601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Exclude plugin crashes from the count below because we report them via 1602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a separate UMA metric. 1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (child_details->type() != ChildProcessInfo::PLUGIN_PROCESS) { 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IncrementPrefValue(prefs::kStabilityChildProcessCrashCount); 1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 16093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED() << "Unexpected notification type " << type.value; 1610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Recursively counts the number of bookmarks and folders in node. 1615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void CountBookmarks(const BookmarkNode* node, 1616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* bookmarks, 1617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int* folders) { 1618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (node->type() == BookmarkNode::URL) 1619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*bookmarks)++; 1620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 1621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*folders)++; 1622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < node->child_count(); ++i) 1623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CountBookmarks(node->GetChild(i), bookmarks, folders); 1624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogBookmarks(const BookmarkNode* node, 16273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* num_bookmarks_key, 16283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* num_folders_key) { 1629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(node); 1630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_bookmarks = 0; 1631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_folders = 0; 1632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CountBookmarks(node, &num_bookmarks, &num_folders); 1633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_folders--; // Don't include the root folder in the count. 1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 1636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 1637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInteger(num_bookmarks_key, num_bookmarks); 1638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInteger(num_folders_key, num_folders); 1639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogBookmarks(BookmarkModel* model) { 1642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(model); 1643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogBookmarks(model->GetBookmarkBarNode(), 1644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kNumBookmarksOnBookmarkBar, 1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kNumFoldersOnBookmarkBar); 1646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogBookmarks(model->other_node(), 1647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kNumBookmarksInOtherBookmarkFolder, 1648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs::kNumFoldersInOtherBookmarkFolder); 1649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleNextStateSave(); 1650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::LogKeywords(const TemplateURLModel* url_model) { 1653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(url_model); 1654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInteger(prefs::kNumKeywords, 1658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>(url_model->GetTemplateURLs().size())); 1659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScheduleNextStateSave(); 1660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecordPluginChanges(PrefService* pref) { 1663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListPrefUpdate update(pref, prefs::kStabilityPluginStats); 1664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* plugins = update.Get(); 1665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(plugins); 1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::iterator value_iter = plugins->begin(); 1668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch value_iter != plugins->end(); ++value_iter) { 1669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*value_iter)->IsType(Value::TYPE_DICTIONARY)) { 16703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 1672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* plugin_dict = static_cast<DictionaryValue*>(*value_iter); 16753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string plugin_name; 1676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); 1677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (plugin_name.empty()) { 16783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 1680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(viettrungluu): remove conversions 16833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (child_process_stats_buffer_.find(UTF8ToWide(plugin_name)) == 1684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_stats_buffer_.end()) 1685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 1686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ChildProcessStats stats = 16883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick child_process_stats_buffer_[UTF8ToWide(plugin_name)]; 1689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stats.process_launches) { 1690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int launches = 0; 1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); 1692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch launches += stats.process_launches; 1693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, launches); 1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stats.process_crashes) { 1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int crashes = 0; 1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes); 1698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch crashes += stats.process_crashes; 1699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, crashes); 1700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (stats.instances) { 1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int instances = 0; 1703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances); 1704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch instances += stats.instances; 1705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances); 1706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick child_process_stats_buffer_.erase(UTF8ToWide(plugin_name)); 1709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now go through and add dictionaries for plugins that didn't already have 1712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // reports in Local State. 1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::map<std::wstring, ChildProcessStats>::iterator cache_iter = 1714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_stats_buffer_.begin(); 1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cache_iter != child_process_stats_buffer_.end(); ++cache_iter) { 1716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChildProcessStats stats = cache_iter->second; 1717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Insert only plugins information into the plugins list. 1719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ChildProcessInfo::PLUGIN_PROCESS != stats.process_type) 1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 1721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(viettrungluu): remove conversion 17233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string plugin_name = WideToUTF8(cache_iter->first); 1724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* plugin_dict = new DictionaryValue; 1726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetString(prefs::kStabilityPluginName, plugin_name); 1728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, 1729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.process_launches); 1730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, 1731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.process_crashes); 1732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugin_dict->SetInteger(prefs::kStabilityPluginInstances, 1733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stats.instances); 1734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch plugins->Append(plugin_dict); 1735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch child_process_stats_buffer_.clear(); 1737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool MetricsService::CanLogNotification(NotificationType type, 1740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 1741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 1742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We simply don't log anything to UMA if there is a single incognito 1743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // session visible. The problem is that we always notify using the orginal 1744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // profile in order to simplify notification processing. 1745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !BrowserList::IsOffTheRecordSessionActive(); 1746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid MetricsService::RecordBooleanPrefValue(const char* path, bool value) { 1749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(IsSingleThreaded()); 1750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* pref = g_browser_process->local_state(); 1752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 1753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetBoolean(path, value); 1755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordCurrentState(pref); 1756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::RecordCurrentState(PrefService* pref) { 1759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref->SetInt64(prefs::kStabilityLastTimestampSec, Time::Now().ToTimeT()); 1760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RecordPluginChanges(pref); 1762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool IsSingleThreaded() { 17653f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen static base::PlatformThreadId thread_id = 0; 1766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!thread_id) 17673f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen thread_id = base::PlatformThread::CurrentId(); 17683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return base::PlatformThread::CurrentId() == thread_id; 1769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_CHROMEOS) 1772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MetricsService::StartExternalMetrics() { 1773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch external_metrics_ = new chromeos::ExternalMetrics; 1774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch external_metrics_->Start(); 1775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 1777