OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/net/resource_prefetch_predictor_observer.h" | |
6 | |
7 #include <memory> | |
8 #include <string> | |
9 #include <utility> | |
10 | |
11 #include "base/memory/ptr_util.h" | |
12 #include "base/metrics/histogram_macros.h" | |
13 #include "content/public/browser/browser_thread.h" | |
14 #include "content/public/browser/resource_request_info.h" | |
15 #include "net/url_request/url_request.h" | |
16 #include "url/gurl.h" | |
17 | |
18 namespace content { | |
19 class WebContents; | |
20 } | |
21 | |
22 using content::BrowserThread; | |
23 using predictors::ResourcePrefetchPredictor; | |
24 using URLRequestSummary = | |
25 predictors::ResourcePrefetchPredictor::URLRequestSummary; | |
26 | |
27 namespace { | |
28 | |
29 // Enum for measuring statistics pertaining to observed request, responses and | |
30 // redirects. | |
31 enum RequestStats { | |
32 REQUEST_STATS_TOTAL_RESPONSES = 0, | |
33 REQUEST_STATS_TOTAL_PROCESSED_RESPONSES = 1, | |
34 REQUEST_STATS_NO_RESOURCE_REQUEST_INFO = 2, // Not recorded (never was). | |
35 REQUEST_STATS_NO_RENDER_FRAME_ID_FROM_REQUEST_INFO = 3, // Not recorded. | |
36 REQUEST_STATS_MAX = 4, | |
37 }; | |
38 | |
39 // Specific to main frame requests. | |
40 enum MainFrameRequestStats { | |
41 MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS = 0, | |
42 MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS = 1, | |
43 MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS = 2, | |
44 MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS = 3, | |
45 MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES = 4, | |
46 MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES = 5, | |
47 MAIN_FRAME_REQUEST_STATS_MAX = 6, | |
48 }; | |
49 | |
50 void ReportRequestStats(RequestStats stat) { | |
51 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.RequestStats", | |
52 stat, | |
53 REQUEST_STATS_MAX); | |
54 } | |
55 | |
56 void ReportMainFrameRequestStats(MainFrameRequestStats stat) { | |
57 UMA_HISTOGRAM_ENUMERATION("ResourcePrefetchPredictor.MainFrameRequestStats", | |
58 stat, | |
59 MAIN_FRAME_REQUEST_STATS_MAX); | |
60 } | |
61 | |
62 bool TryToFillNavigationID( | |
63 predictors::NavigationID* navigation_id, | |
64 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | |
65 const GURL& main_frame_url, | |
66 const base::TimeTicks& creation_time) { | |
67 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
68 content::WebContents* web_contents = web_contents_getter.Run(); | |
69 if (!web_contents) | |
70 return false; | |
71 *navigation_id = | |
72 predictors::NavigationID(web_contents, main_frame_url, creation_time); | |
73 // A WebContents might be associated with something that is not a tab. | |
74 // In this case tab_id will be -1 and is_valid() will return false. | |
75 return navigation_id->is_valid(); | |
76 } | |
77 | |
78 } // namespace | |
79 | |
80 namespace chrome_browser_net { | |
81 | |
82 ResourcePrefetchPredictorObserver::ResourcePrefetchPredictorObserver( | |
83 ResourcePrefetchPredictor* predictor) | |
84 : predictor_(predictor->AsWeakPtr()) { | |
85 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
86 } | |
87 | |
88 ResourcePrefetchPredictorObserver::~ResourcePrefetchPredictorObserver() { | |
89 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | |
90 BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
91 } | |
92 | |
93 void ResourcePrefetchPredictorObserver::OnRequestStarted( | |
94 net::URLRequest* request, | |
95 content::ResourceType resource_type, | |
96 const content::ResourceRequestInfo::WebContentsGetter& | |
97 web_contents_getter) { | |
98 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
99 | |
100 if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | |
101 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REQUESTS); | |
102 | |
103 if (!ResourcePrefetchPredictor::ShouldRecordRequest(request, resource_type)) | |
104 return; | |
105 | |
106 auto summary = base::MakeUnique<URLRequestSummary>(); | |
107 summary->resource_url = request->original_url(); | |
108 summary->resource_type = resource_type; | |
109 | |
110 BrowserThread::PostTask( | |
111 BrowserThread::UI, FROM_HERE, | |
112 base::BindOnce( | |
113 &ResourcePrefetchPredictorObserver::OnRequestStartedOnUIThread, | |
114 base::Unretained(this), base::Passed(std::move(summary)), | |
115 web_contents_getter, request->first_party_for_cookies(), | |
116 request->creation_time())); | |
117 | |
118 if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | |
119 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REQUESTS); | |
120 } | |
121 | |
122 void ResourcePrefetchPredictorObserver::OnRequestRedirected( | |
123 net::URLRequest* request, | |
124 const GURL& redirect_url, | |
125 const content::ResourceRequestInfo::WebContentsGetter& | |
126 web_contents_getter) { | |
127 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
128 | |
129 const content::ResourceRequestInfo* request_info = | |
130 content::ResourceRequestInfo::ForRequest(request); | |
131 if (request_info && | |
132 request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) { | |
133 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_REDIRECTS); | |
134 } | |
135 | |
136 if (!ResourcePrefetchPredictor::ShouldRecordRedirect(request)) | |
137 return; | |
138 | |
139 auto summary = base::MakeUnique<URLRequestSummary>(); | |
140 if (!ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( | |
141 *request, summary.get())) { | |
142 return; | |
143 } | |
144 summary->redirect_url = redirect_url; | |
145 | |
146 BrowserThread::PostTask( | |
147 BrowserThread::UI, FROM_HERE, | |
148 base::BindOnce( | |
149 &ResourcePrefetchPredictorObserver::OnRequestRedirectedOnUIThread, | |
150 base::Unretained(this), base::Passed(std::move(summary)), | |
151 web_contents_getter, request->first_party_for_cookies(), | |
152 request->creation_time())); | |
153 | |
154 if (request_info && | |
155 request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) { | |
156 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_REDIRECTS); | |
157 } | |
158 } | |
159 | |
160 void ResourcePrefetchPredictorObserver::OnResponseStarted( | |
161 net::URLRequest* request, | |
162 const content::ResourceRequestInfo::WebContentsGetter& | |
163 web_contents_getter) { | |
164 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
165 | |
166 ReportRequestStats(REQUEST_STATS_TOTAL_RESPONSES); | |
167 | |
168 const content::ResourceRequestInfo* request_info = | |
169 content::ResourceRequestInfo::ForRequest(request); | |
170 if (request_info && | |
171 request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) { | |
172 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_TOTAL_RESPONSES); | |
173 } | |
174 | |
175 if (!ResourcePrefetchPredictor::ShouldRecordResponse(request)) | |
176 return; | |
177 auto summary = base::MakeUnique<URLRequestSummary>(); | |
178 if (!ResourcePrefetchPredictor::URLRequestSummary::SummarizeResponse( | |
179 *request, summary.get())) { | |
180 return; | |
181 } | |
182 | |
183 BrowserThread::PostTask( | |
184 BrowserThread::UI, FROM_HERE, | |
185 base::BindOnce( | |
186 &ResourcePrefetchPredictorObserver::OnResponseStartedOnUIThread, | |
187 base::Unretained(this), base::Passed(std::move(summary)), | |
188 web_contents_getter, request->first_party_for_cookies(), | |
189 request->creation_time())); | |
190 | |
191 ReportRequestStats(REQUEST_STATS_TOTAL_PROCESSED_RESPONSES); | |
192 if (request_info && | |
193 request_info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME) { | |
194 ReportMainFrameRequestStats(MAIN_FRAME_REQUEST_STATS_PROCESSED_RESPONSES); | |
195 } | |
196 } | |
197 | |
198 void ResourcePrefetchPredictorObserver::OnRequestStartedOnUIThread( | |
199 std::unique_ptr<URLRequestSummary> summary, | |
200 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | |
201 const GURL& main_frame_url, | |
202 const base::TimeTicks& creation_time) const { | |
203 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
204 if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter, | |
205 main_frame_url, creation_time)) { | |
206 return; | |
207 } | |
208 predictor_->RecordURLRequest(*summary); | |
209 } | |
210 | |
211 void ResourcePrefetchPredictorObserver::OnRequestRedirectedOnUIThread( | |
212 std::unique_ptr<URLRequestSummary> summary, | |
213 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | |
214 const GURL& main_frame_url, | |
215 const base::TimeTicks& creation_time) const { | |
216 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
217 if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter, | |
218 main_frame_url, creation_time)) { | |
219 return; | |
220 } | |
221 predictor_->RecordURLRedirect(*summary); | |
222 } | |
223 | |
224 void ResourcePrefetchPredictorObserver::OnResponseStartedOnUIThread( | |
225 std::unique_ptr<URLRequestSummary> summary, | |
226 const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, | |
227 const GURL& main_frame_url, | |
228 const base::TimeTicks& creation_time) const { | |
229 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
230 if (!TryToFillNavigationID(&summary->navigation_id, web_contents_getter, | |
231 main_frame_url, creation_time)) { | |
232 return; | |
233 } | |
234 predictor_->RecordURLResponse(*summary); | |
235 } | |
236 | |
237 } // namespace chrome_browser_net | |
OLD | NEW |