|
OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ | |
6 #define CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ | |
7 #pragma once | |
8 | |
9 #include <string> | |
10 #include <vector> | |
jar (doing other things)
2011/11/03 06:23:15
nit: add #include <map>
ramant (doing other things)
2011/11/03 21:51:39
Done.
| |
11 | |
12 #include "base/basictypes.h" | |
13 #include "base/memory/ref_counted.h" | |
14 #include "base/time.h" | |
15 #include "base/values.h" | |
16 #include "content/common/child_process_info.h" | |
17 | |
18 // This class maintains state that is used to upload tracking data from the | |
19 // various processes, into the browser process. Such transactions are usually | |
20 // instigated by the browser. In general, a process will respond by gathering | |
21 // tracking data, and transmitting the pickled tracking data. We collect the | |
22 // data in asynchronous mode that doesn't block the UI thread. | |
23 // | |
24 // To assure that all the processes have responded, a counter is maintained | |
25 // to indicate the number of pending (not yet responsive) processes. We tag | |
26 // each group of requests with a sequence number. For each group of requests, we | |
27 // create RequestContext object which stores the sequence number, pending | |
28 // processes and the CallbackObject that needs to be notified when we receive an | |
29 // update from processes. When an update arrives we find the RequestContext | |
30 // associated with sequence number and send the unpickled tracking data to the | |
31 // |callback_object|. | |
32 | |
33 namespace chrome_browser_metrics { | |
34 | |
35 // TODO(rtenneti): Delete/replace this class after flushing out exact | |
36 // interface/integration with the UI (about CallbackObject). | |
37 class CallbackObject : public base::RefCountedThreadSafe<CallbackObject> { | |
38 public: | |
39 CallbackObject() : value_(NULL) {} | |
40 | |
41 // Returns the data from renderer process in |value|. Transfers ownership of | |
42 // |value| to the entity that supplied this callback. It is then | |
43 // responsibility of the implementation of SendData() to eventually delete | |
44 // |value|. | |
45 void SendData(base::DictionaryValue* value) {value_ = value; } | |
46 | |
47 base::DictionaryValue* GetValue() {return value_; } | |
48 | |
49 private: | |
50 friend class base::RefCountedThreadSafe<CallbackObject>; | |
51 virtual ~CallbackObject() {} | |
52 | |
53 base::DictionaryValue* value_; | |
54 | |
55 DISALLOW_COPY_AND_ASSIGN(CallbackObject); | |
56 }; | |
57 | |
58 class TrackingSynchronizer : public | |
59 base::RefCountedThreadSafe<TrackingSynchronizer> { | |
60 public: | |
61 // The "RequestContext" structure describes an individual request received | |
62 // from the UI. | |
63 struct RequestContext { | |
64 RequestContext(scoped_refptr<CallbackObject> callback_object, | |
65 int sequence_number, | |
66 int processes_pending, | |
67 base::TimeTicks callback_start_time) | |
68 : callback_object_(callback_object), | |
69 sequence_number_(sequence_number), | |
70 processes_pending_(processes_pending), | |
71 request_start_time_(callback_start_time) { | |
72 } | |
73 | |
74 ~RequestContext() {} | |
75 | |
76 // Requests are made to asynchronously send data to the |callback_object_|. | |
77 scoped_refptr<CallbackObject> callback_object_; | |
78 | |
79 // The sequence number used by the most recent update request to contact all | |
80 // processes. | |
81 int sequence_number_; | |
82 | |
83 // The number of processes that have not yet responded to requests. | |
84 int processes_pending_; | |
85 | |
86 // The time when we were told to start the fetching of data from processes. | |
87 base::TimeTicks request_start_time_; | |
88 }; | |
89 | |
90 // A map from sequence_number_ to the actual RequestContexts. | |
91 typedef std::map<int, RequestContext*> RequestContextMap; | |
92 | |
93 // Construction also sets up the global singleton instance. This instance is | |
94 // used to communicate between the IO and UI thread, and is destroyed only as | |
95 // the main thread (browser_main) terminates, which means the IO thread has | |
96 // already completed, and will not need this instance any further. | |
97 TrackingSynchronizer(); | |
98 | |
99 // Return pointer to the singleton instance, which is allocated and | |
100 // deallocated on the main UI thread (during system startup and teardown). | |
101 static TrackingSynchronizer* CurrentSynchronizer(); | |
102 | |
103 // Contact all processes, and get them to upload to the browser any/all | |
104 // changes to tracking data. This gets the ThreadData from browser process | |
105 // immediately. This method is accessible on UI thread. | |
106 // Used for testing purposes only. | |
107 static void FetchTrackingDataSynchronously(std::string* output); | |
jar (doing other things)
2011/11/03 06:23:15
nit: probably should have todo() to remove this wh
ramant (doing other things)
2011/11/03 21:51:39
Done.
| |
108 | |
109 // Contact all processes, and get them to upload to the browser any/all | |
110 // changes to tracking data. It calls |callback_object|'s SetData method with | |
111 // the data received from each sub-process. | |
112 // This method is accessible on UI thread. | |
113 static void FetchTrackingDataAsynchronously( | |
114 scoped_refptr<CallbackObject> callback_object); | |
115 | |
116 // Contact all processes and set tracking status to |enable|. | |
117 // This method is accessible on UI thread. | |
118 static void SetTrackingStatus(bool enable); | |
119 | |
120 // Respond to this message from the renderer by setting the tracking status | |
121 // (SetTrackingStatusInProcess) in that renderer process. | |
122 // |process_id| is used to find the renderer process. | |
123 // This method is accessible on IO thread. | |
124 static void IsTrackingEnabled(int process_id); | |
125 | |
126 // Get the current tracking status from the browser process and set it in the | |
127 // renderer process. |process_id| is used to find the renderer process. | |
128 // This method is accessible on UI thread. | |
129 static void SetTrackingStatusInProcess(int process_id); | |
130 | |
131 // Deserialize the tracking data and record that we have received tracking | |
132 // data from a process. | |
133 // This method is accessible on IO thread. | |
134 static void DeserializeTrackingList( | |
135 int sequence_number, | |
136 const std::string& tracking_data, | |
137 ChildProcessInfo::ProcessType process_type); | |
138 | |
139 private: | |
140 friend class base::RefCountedThreadSafe<TrackingSynchronizer>; | |
141 | |
142 virtual ~TrackingSynchronizer(); | |
143 | |
144 // Establish a new sequence_number_, and use it to notify all the processes of | |
145 // the need to supply, to the browser, their tracking data. It also registers | |
146 // |callback_object| in |outstanding_requests_| map. | |
147 // Return the sequence_number_ that was used. | |
148 // This method is accessible on UI thread. | |
149 int RegisterAndNotifyAllProcesses( | |
150 scoped_refptr<CallbackObject> callback_object); | |
151 | |
152 // It finds the CallbackObject in |outstanding_requests_| map for the given | |
153 // |sequence_number| and notifies the CallbackObject about the |value|. This | |
154 // is called whenever we receive tracked data from processes. It also records | |
155 // that we are waiting for one less tracking data from a process for the given | |
156 // sequence number. If we have received a response from all renderers, then it | |
157 // deletes the entry for sequence_number from |outstanding_requests_| map. | |
158 // This method is accessible on UI thread. | |
159 void DecrementPendingProcessesAndSendData(int sequence_number, | |
160 base::DictionaryValue* value); | |
161 | |
162 // Records that we are waiting for one less tracking data from a process for | |
163 // the given sequence number. | |
164 // This method is accessible on UI thread. | |
165 void DecrementPendingProcesses(int sequence_number); | |
166 | |
167 // When all changes have been acquired, or when the wait time expires | |
168 // (whichever is sooner), this method is called. This method deletes the entry | |
169 // for the given sequence_number from |outstanding_requests_| map. | |
170 // This method is accessible on UI thread. | |
171 void ForceTrackingSynchronizationDoneCallback(int sequence_number); | |
172 | |
173 // Get a new sequence number to be sent to processes from browser process. | |
174 // This method is accessible on UI thread. | |
175 int GetNextAvailableSequenceNumber(); | |
176 | |
177 // Map of all outstanding RequestContexts, from sequence_number_ to | |
178 // RequestContext. | |
179 RequestContextMap outstanding_requests_; | |
180 | |
181 // We don't track the actual processes that are contacted for an update, only | |
182 // the count of the number of processes, and we can sometimes time-out and | |
183 // give up on a "slow to respond" process. We use a sequence_number to be | |
184 // sure a response from a process is associated with the current round of | |
185 // requests. All sequence numbers used are non-negative. | |
186 // last_used_sequence_number_ is the most recently used number (used to avoid | |
187 // reuse for a long time). | |
188 int last_used_sequence_number_; | |
189 | |
190 // This singleton instance should be started during the single threaded | |
191 // portion of main(). It initializes globals to provide support for all future | |
192 // calls. This object is created on the UI thread, and it is destroyed after | |
193 // all the other threads have gone away. As a result, it is ok to call it | |
194 // from the UI thread, or for about:tracking. | |
195 static TrackingSynchronizer* tracking_synchronizer_; | |
196 | |
197 DISALLOW_COPY_AND_ASSIGN(TrackingSynchronizer); | |
198 }; | |
199 | |
200 } // namespace chrome_browser_metrics | |
201 | |
202 #endif // CHROME_BROWSER_METRICS_TRACKING_SYNCHRONIZER_H_ | |
OLD | NEW |