[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / browser / histogram_synchronizer.h
blob0968abdf7892ba3f912caa609900c63854ff3cf7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
6 #define CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_
8 #include <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/memory/singleton.h"
14 #include "base/synchronization/lock.h"
15 #include "base/time.h"
16 #include "content/browser/histogram_subscriber.h"
18 class MessageLoop;
20 namespace content {
22 // This class maintains state that is used to upload histogram data from the
23 // various child processes, into the browser process. Such transactions are
24 // usually instigated by the browser. In general, a child process will respond
25 // by gathering snapshots of all internal histograms, calculating what has
26 // changed since its last upload, and transmitting a pickled collection of
27 // deltas.
29 // There are actually two modes of update request. One is synchronous (and
30 // blocks the UI thread, waiting to populate an about:histograms tab) and the
31 // other is asynchronous, and used by the metrics services in preparation for a
32 // log upload.
34 // To assure that all the processes have responded, a counter is maintained to
35 // indicate the number of pending (not yet responsive) processes. To avoid
36 // confusion about a response (i.e., is the process responding to a current
37 // request for an update, or to an old request for an update) we tag each group
38 // of requests with a sequence number. When an update arrives we can ignore it
39 // (relative to the counter) if it does not relate to a current outstanding
40 // sequence number.
42 // There is one final mode of use, where a renderer spontaneously decides to
43 // transmit a collection of histogram data. This is designed for use when the
44 // renderer is terminating. Unfortunately, renders may be terminated without
45 // warning, and the best we can do is periodically acquire data from a tab, such
46 // as when a page load has completed. In this mode, the renderer uses a
47 // reserved sequence number, different from any sequence number that might be
48 // specified by a browser request. Since this sequence number can't match an
49 // outstanding sequence number, the pickled data is accepted into the browser,
50 // but there is no impact on the counters.
52 class HistogramSynchronizer : public HistogramSubscriber {
53 public:
54 enum ProcessHistogramRequester {
55 UNKNOWN,
56 ASYNC_HISTOGRAMS,
59 // Return pointer to the singleton instance for the current process, or NULL
60 // if none.
61 static HistogramSynchronizer* GetInstance();
63 // Contact all processes, and get them to upload to the browser any/all
64 // changes to histograms. This method is called from about:histograms.
65 static void FetchHistograms();
67 // Contact all child processes, and get them to upload to the browser any/all
68 // changes to histograms. When all changes have been acquired, or when the
69 // wait time expires (whichever is sooner), post the callback to the
70 // specified message loop. Note the callback is posted exactly once.
71 static void FetchHistogramsAsynchronously(MessageLoop* callback_thread,
72 const base::Closure& callback,
73 base::TimeDelta wait_time);
75 private:
76 friend struct DefaultSingletonTraits<HistogramSynchronizer>;
78 class RequestContext;
80 HistogramSynchronizer();
81 virtual ~HistogramSynchronizer();
83 // Establish a new sequence number, and use it to notify all processes
84 // (renderers, plugins, GPU, etc) of the need to supply, to the browser,
85 // any/all changes to their histograms. |wait_time| specifies the amount of
86 // time to wait before cancelling the requests for non-responsive processes.
87 void RegisterAndNotifyAllProcesses(ProcessHistogramRequester requester,
88 base::TimeDelta wait_time);
90 // -------------------------------------------------------
91 // HistogramSubscriber methods for browser child processes
92 // -------------------------------------------------------
94 // Update the number of pending processes for the given |sequence_number|.
95 // This is called on UI thread.
96 virtual void OnPendingProcesses(int sequence_number,
97 int pending_processes,
98 bool end) OVERRIDE;
100 // Send histogram_data back to caller and also record that we are waiting
101 // for one less histogram data from child process for the given sequence
102 // number. This method is accessible on UI thread.
103 virtual void OnHistogramDataCollected(
104 int sequence_number,
105 const std::vector<std::string>& pickled_histograms) OVERRIDE;
107 // Set the callback_thread_ and callback_ members. If these members already
108 // had values, then as a side effect, post the old callback_ to the old
109 // callaback_thread_. This side effect should not generally happen, but is in
110 // place to assure correctness (that any tasks that were set, are eventually
111 // called, and never merely discarded).
112 void SetCallbackTaskAndThread(MessageLoop* callback_thread,
113 const base::Closure& callback);
115 void ForceHistogramSynchronizationDoneCallback(int sequence_number);
117 // Internal helper function, to post task, and record callback stats.
118 void InternalPostTask(MessageLoop* thread, const base::Closure& callback);
120 // Gets a new sequence number to be sent to processes from browser process.
121 int GetNextAvailableSequenceNumber(ProcessHistogramRequester requester);
123 // This lock_ protects access to all members.
124 base::Lock lock_;
126 // When a request is made to asynchronously update the histograms, we store
127 // the task and thread we use to post a completion notification in
128 // callback_ and callback_thread_.
129 base::Closure callback_;
130 MessageLoop* callback_thread_;
132 // We don't track the actual processes that are contacted for an update, only
133 // the count of the number of processes, and we can sometimes time-out and
134 // give up on a "slow to respond" process. We use a sequence_number to be
135 // sure a response from a process is associated with the current round of
136 // requests (and not merely a VERY belated prior response).
137 // All sequence numbers used are non-negative.
138 // last_used_sequence_number_ is the most recently used number (used to avoid
139 // reuse for a long time).
140 int last_used_sequence_number_;
142 // The sequence number used by the most recent asynchronous update request to
143 // contact all processes.
144 int async_sequence_number_;
146 DISALLOW_COPY_AND_ASSIGN(HistogramSynchronizer);
149 } // namespace content
151 #endif // CONTENT_BROWSER_HISTOGRAM_SYNCHRONIZER_H_