OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | 5 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <ostream> | 8 #include <ostream> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "ipc/ipc_message.h" | 30 #include "ipc/ipc_message.h" |
31 #include "ipc/ipc_message_macros.h" | 31 #include "ipc/ipc_message_macros.h" |
32 #include "net/base/net_errors.h" | 32 #include "net/base/net_errors.h" |
33 #include "ui/base/page_transition_types.h" | 33 #include "ui/base/page_transition_types.h" |
34 | 34 |
35 DEFINE_WEB_CONTENTS_USER_DATA_KEY( | 35 DEFINE_WEB_CONTENTS_USER_DATA_KEY( |
36 page_load_metrics::MetricsWebContentsObserver); | 36 page_load_metrics::MetricsWebContentsObserver); |
37 | 37 |
38 namespace page_load_metrics { | 38 namespace page_load_metrics { |
39 | 39 |
| 40 namespace { |
| 41 |
| 42 UserInitiatedInfo CreateUserInitiatedInfo( |
| 43 content::NavigationHandle* navigation_handle, |
| 44 PageLoadTracker* committed_load) { |
| 45 if (!navigation_handle->IsRendererInitiated()) |
| 46 return UserInitiatedInfo::BrowserInitiated(); |
| 47 |
| 48 return UserInitiatedInfo::RenderInitiated( |
| 49 navigation_handle->HasUserGesture(), |
| 50 committed_load && |
| 51 committed_load->input_tracker()->FindAndConsumeInputEventsBefore( |
| 52 navigation_handle->NavigationStart())); |
| 53 } |
| 54 |
| 55 } // namespace |
| 56 |
40 // static | 57 // static |
41 MetricsWebContentsObserver::MetricsWebContentsObserver( | 58 MetricsWebContentsObserver::MetricsWebContentsObserver( |
42 content::WebContents* web_contents, | 59 content::WebContents* web_contents, |
43 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) | 60 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) |
44 : content::WebContentsObserver(web_contents), | 61 : content::WebContentsObserver(web_contents), |
45 in_foreground_(false), | 62 in_foreground_(false), |
46 embedder_interface_(std::move(embedder_interface)), | 63 embedder_interface_(std::move(embedder_interface)), |
47 has_navigated_(false) { | 64 has_navigated_(false) { |
48 RegisterInputEventObserver(web_contents->GetRenderViewHost()); | 65 RegisterInputEventObserver(web_contents->GetRenderViewHost()); |
49 } | 66 } |
50 | 67 |
51 MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents( | 68 MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents( |
52 content::WebContents* web_contents, | 69 content::WebContents* web_contents, |
53 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) { | 70 std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface) { |
54 DCHECK(web_contents); | 71 DCHECK(web_contents); |
55 | 72 |
56 MetricsWebContentsObserver* metrics = FromWebContents(web_contents); | 73 MetricsWebContentsObserver* metrics = FromWebContents(web_contents); |
57 if (!metrics) { | 74 if (!metrics) { |
58 metrics = new MetricsWebContentsObserver(web_contents, | 75 metrics = new MetricsWebContentsObserver(web_contents, |
59 std::move(embedder_interface)); | 76 std::move(embedder_interface)); |
60 web_contents->SetUserData(UserDataKey(), metrics); | 77 web_contents->SetUserData(UserDataKey(), metrics); |
61 } | 78 } |
62 return metrics; | 79 return metrics; |
63 } | 80 } |
64 | 81 |
65 MetricsWebContentsObserver::~MetricsWebContentsObserver() { | 82 MetricsWebContentsObserver::~MetricsWebContentsObserver() { |
66 // TODO(csharrison): Use a more user-initiated signal for CLOSE. | 83 // TODO(csharrison): Use a more user-initiated signal for CLOSE. |
67 NotifyAbortAllLoads(ABORT_CLOSE, false); | 84 NotifyAbortAllLoads(ABORT_CLOSE, UserInitiatedInfo::NotUserInitiated()); |
68 } | 85 } |
69 | 86 |
70 void MetricsWebContentsObserver::RegisterInputEventObserver( | 87 void MetricsWebContentsObserver::RegisterInputEventObserver( |
71 content::RenderViewHost* host) { | 88 content::RenderViewHost* host) { |
72 if (host != nullptr) | 89 if (host != nullptr) |
73 host->GetWidget()->AddInputEventObserver(this); | 90 host->GetWidget()->AddInputEventObserver(this); |
74 } | 91 } |
75 | 92 |
76 void MetricsWebContentsObserver::UnregisterInputEventObserver( | 93 void MetricsWebContentsObserver::UnregisterInputEventObserver( |
77 content::RenderViewHost* host) { | 94 content::RenderViewHost* host) { |
(...skipping 22 matching lines...) Expand all Loading... |
100 } | 117 } |
101 | 118 |
102 void MetricsWebContentsObserver::WillStartNavigationRequest( | 119 void MetricsWebContentsObserver::WillStartNavigationRequest( |
103 content::NavigationHandle* navigation_handle) { | 120 content::NavigationHandle* navigation_handle) { |
104 // Same-page navigations should never go through WillStartNavigationRequest. | 121 // Same-page navigations should never go through WillStartNavigationRequest. |
105 DCHECK(!navigation_handle->IsSamePage()); | 122 DCHECK(!navigation_handle->IsSamePage()); |
106 | 123 |
107 if (!navigation_handle->IsInMainFrame()) | 124 if (!navigation_handle->IsInMainFrame()) |
108 return; | 125 return; |
109 | 126 |
| 127 UserInitiatedInfo user_initiated_info( |
| 128 CreateUserInitiatedInfo(navigation_handle, committed_load_.get())); |
110 std::unique_ptr<PageLoadTracker> last_aborted = | 129 std::unique_ptr<PageLoadTracker> last_aborted = |
111 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle); | 130 NotifyAbortedProvisionalLoadsNewNavigation(navigation_handle, |
| 131 user_initiated_info); |
112 | 132 |
113 int chain_size_same_url = 0; | 133 int chain_size_same_url = 0; |
114 int chain_size = 0; | 134 int chain_size = 0; |
115 if (last_aborted) { | 135 if (last_aborted) { |
116 if (last_aborted->MatchesOriginalNavigation(navigation_handle)) { | 136 if (last_aborted->MatchesOriginalNavigation(navigation_handle)) { |
117 chain_size_same_url = last_aborted->aborted_chain_size_same_url() + 1; | 137 chain_size_same_url = last_aborted->aborted_chain_size_same_url() + 1; |
118 } else if (last_aborted->aborted_chain_size_same_url() > 0) { | 138 } else if (last_aborted->aborted_chain_size_same_url() > 0) { |
119 LogAbortChainSameURLHistogram( | 139 LogAbortChainSameURLHistogram( |
120 last_aborted->aborted_chain_size_same_url()); | 140 last_aborted->aborted_chain_size_same_url()); |
121 } | 141 } |
(...skipping 22 matching lines...) Expand all Loading... |
144 // from the omnibox. | 164 // from the omnibox. |
145 DCHECK_GT(2ul, provisional_loads_.size()); | 165 DCHECK_GT(2ul, provisional_loads_.size()); |
146 // Passing raw pointers to observers_ and embedder_interface_ is safe because | 166 // Passing raw pointers to observers_ and embedder_interface_ is safe because |
147 // the MetricsWebContentsObserver owns them both list and they are torn down | 167 // the MetricsWebContentsObserver owns them both list and they are torn down |
148 // after the PageLoadTracker. The PageLoadTracker does not hold on to | 168 // after the PageLoadTracker. The PageLoadTracker does not hold on to |
149 // committed_load_ or navigation_handle beyond the scope of the constructor. | 169 // committed_load_ or navigation_handle beyond the scope of the constructor. |
150 provisional_loads_.insert(std::make_pair( | 170 provisional_loads_.insert(std::make_pair( |
151 navigation_handle, | 171 navigation_handle, |
152 base::MakeUnique<PageLoadTracker>( | 172 base::MakeUnique<PageLoadTracker>( |
153 in_foreground_, embedder_interface_.get(), currently_committed_url, | 173 in_foreground_, embedder_interface_.get(), currently_committed_url, |
154 navigation_handle, chain_size, chain_size_same_url))); | 174 navigation_handle, user_initiated_info, chain_size, |
| 175 chain_size_same_url))); |
155 } | 176 } |
156 | 177 |
157 void MetricsWebContentsObserver::OnRequestComplete( | 178 void MetricsWebContentsObserver::OnRequestComplete( |
158 content::ResourceType resource_type, | 179 content::ResourceType resource_type, |
159 bool was_cached, | 180 bool was_cached, |
160 int net_error) { | 181 int net_error) { |
161 // For simplicity, only count subresources. Navigations are hard to attribute | 182 // For simplicity, only count subresources. Navigations are hard to attribute |
162 // here because we won't have a committed load by the time data streams in | 183 // here because we won't have a committed load by the time data streams in |
163 // from the IO thread. | 184 // from the IO thread. |
164 if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME && | 185 if (resource_type == content::RESOURCE_TYPE_MAIN_FRAME && |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 return; | 223 return; |
203 } | 224 } |
204 | 225 |
205 const bool should_track = | 226 const bool should_track = |
206 finished_nav && ShouldTrackNavigation(navigation_handle); | 227 finished_nav && ShouldTrackNavigation(navigation_handle); |
207 | 228 |
208 if (finished_nav && !should_track) | 229 if (finished_nav && !should_track) |
209 finished_nav->StopTracking(); | 230 finished_nav->StopTracking(); |
210 | 231 |
211 if (navigation_handle->HasCommitted()) { | 232 if (navigation_handle->HasCommitted()) { |
| 233 UserInitiatedInfo user_initiated_info = |
| 234 finished_nav |
| 235 ? finished_nav->user_initiated_info() |
| 236 : CreateUserInitiatedInfo(navigation_handle, committed_load_.get()); |
| 237 |
212 // Notify other loads that they may have been aborted by this committed | 238 // Notify other loads that they may have been aborted by this committed |
213 // load. is_certainly_browser_timestamp is set to false because | 239 // load. is_certainly_browser_timestamp is set to false because |
214 // NavigationStart() could be set in either the renderer or browser process. | 240 // NavigationStart() could be set in either the renderer or browser process. |
215 NotifyAbortAllLoadsWithTimestamp( | 241 NotifyAbortAllLoadsWithTimestamp( |
216 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), | 242 AbortTypeForPageTransition(navigation_handle->GetPageTransition()), |
217 IsNavigationUserInitiated(navigation_handle), | 243 user_initiated_info, navigation_handle->NavigationStart(), false); |
218 navigation_handle->NavigationStart(), false); | |
219 | 244 |
220 if (should_track) { | 245 if (should_track) { |
221 HandleCommittedNavigationForTrackedLoad(navigation_handle, | 246 HandleCommittedNavigationForTrackedLoad(navigation_handle, |
222 std::move(finished_nav)); | 247 std::move(finished_nav)); |
223 } else { | 248 } else { |
224 committed_load_.reset(); | 249 committed_load_.reset(); |
225 } | 250 } |
226 } else if (should_track) { | 251 } else if (should_track) { |
227 HandleFailedNavigationForTrackedLoad(navigation_handle, | 252 HandleFailedNavigationForTrackedLoad(navigation_handle, |
228 std::move(finished_nav)); | 253 std::move(finished_nav)); |
229 } | 254 } |
230 } | 255 } |
231 | 256 |
232 // Handle a pre-commit error. Navigations that result in an error page will be | 257 // Handle a pre-commit error. Navigations that result in an error page will be |
233 // ignored. | 258 // ignored. |
234 void MetricsWebContentsObserver::HandleFailedNavigationForTrackedLoad( | 259 void MetricsWebContentsObserver::HandleFailedNavigationForTrackedLoad( |
235 content::NavigationHandle* navigation_handle, | 260 content::NavigationHandle* navigation_handle, |
236 std::unique_ptr<PageLoadTracker> tracker) { | 261 std::unique_ptr<PageLoadTracker> tracker) { |
237 tracker->FailedProvisionalLoad(navigation_handle); | 262 tracker->FailedProvisionalLoad(navigation_handle); |
238 | 263 |
239 net::Error error = navigation_handle->GetNetErrorCode(); | 264 net::Error error = navigation_handle->GetNetErrorCode(); |
240 | 265 |
241 // net::OK: This case occurs when the NavigationHandle finishes and reports | 266 // net::OK: This case occurs when the NavigationHandle finishes and reports |
242 // !HasCommitted(), but reports no net::Error. This should not occur | 267 // !HasCommitted(), but reports no net::Error. This should not occur |
243 // pre-PlzNavigate, but afterwards it should represent the navigation stopped | 268 // pre-PlzNavigate, but afterwards it should represent the navigation stopped |
244 // by the user before it was ready to commit. | 269 // by the user before it was ready to commit. |
245 // net::ERR_ABORTED: An aborted provisional load has error | 270 // net::ERR_ABORTED: An aborted provisional load has error |
246 // net::ERR_ABORTED. | 271 // net::ERR_ABORTED. |
247 if ((error == net::OK) || (error == net::ERR_ABORTED)) { | 272 if ((error == net::OK) || (error == net::ERR_ABORTED)) { |
248 tracker->NotifyAbort(ABORT_OTHER, false, base::TimeTicks::Now(), true); | 273 tracker->NotifyAbort(ABORT_OTHER, UserInitiatedInfo::NotUserInitiated(), |
| 274 base::TimeTicks::Now(), true); |
249 aborted_provisional_loads_.push_back(std::move(tracker)); | 275 aborted_provisional_loads_.push_back(std::move(tracker)); |
250 } | 276 } |
251 } | 277 } |
252 | 278 |
253 void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad( | 279 void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad( |
254 content::NavigationHandle* navigation_handle, | 280 content::NavigationHandle* navigation_handle, |
255 std::unique_ptr<PageLoadTracker> tracker) { | 281 std::unique_ptr<PageLoadTracker> tracker) { |
256 if (!IsNavigationUserInitiated(navigation_handle) && | 282 if (!IsNavigationUserInitiated(navigation_handle) && |
257 (navigation_handle->GetPageTransition() & | 283 (navigation_handle->GetPageTransition() & |
258 ui::PAGE_TRANSITION_CLIENT_REDIRECT) != 0 && | 284 ui::PAGE_TRANSITION_CLIENT_REDIRECT) != 0 && |
259 committed_load_) | 285 committed_load_) { |
| 286 // TODO(bmcquade): consider carrying the user_gesture bit forward to the |
| 287 // redirected navigation. |
260 committed_load_->NotifyClientRedirectTo(*tracker); | 288 committed_load_->NotifyClientRedirectTo(*tracker); |
| 289 } |
261 | 290 |
262 committed_load_ = std::move(tracker); | 291 committed_load_ = std::move(tracker); |
263 committed_load_->Commit(navigation_handle); | 292 committed_load_->Commit(navigation_handle); |
264 } | 293 } |
265 | 294 |
266 void MetricsWebContentsObserver::NavigationStopped() { | 295 void MetricsWebContentsObserver::NavigationStopped() { |
267 // TODO(csharrison): Use a more user-initiated signal for STOP. | 296 // TODO(csharrison): Use a more user-initiated signal for STOP. |
268 NotifyAbortAllLoads(ABORT_STOP, false); | 297 NotifyAbortAllLoads(ABORT_STOP, UserInitiatedInfo::NotUserInitiated()); |
269 } | 298 } |
270 | 299 |
271 void MetricsWebContentsObserver::OnInputEvent( | 300 void MetricsWebContentsObserver::OnInputEvent( |
272 const blink::WebInputEvent& event) { | 301 const blink::WebInputEvent& event) { |
273 // Ignore browser navigation or reload which comes with type Undefined. | 302 // Ignore browser navigation or reload which comes with type Undefined. |
274 if (event.type == blink::WebInputEvent::Type::Undefined) | 303 if (event.type == blink::WebInputEvent::Type::Undefined) |
275 return; | 304 return; |
276 | 305 |
277 if (committed_load_) | 306 if (committed_load_) |
278 committed_load_->OnInputEvent(event); | 307 committed_load_->OnInputEvent(event); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 return; | 369 return; |
341 } | 370 } |
342 | 371 |
343 // If this is a crash, eagerly log the aborted provisional loads and the | 372 // If this is a crash, eagerly log the aborted provisional loads and the |
344 // committed load. |provisional_loads_| don't need to be destroyed here | 373 // committed load. |provisional_loads_| don't need to be destroyed here |
345 // because their lifetime is tied to the NavigationHandle. | 374 // because their lifetime is tied to the NavigationHandle. |
346 committed_load_.reset(); | 375 committed_load_.reset(); |
347 aborted_provisional_loads_.clear(); | 376 aborted_provisional_loads_.clear(); |
348 } | 377 } |
349 | 378 |
350 void MetricsWebContentsObserver::NotifyAbortAllLoads(UserAbortType abort_type, | 379 void MetricsWebContentsObserver::NotifyAbortAllLoads( |
351 bool user_initiated) { | 380 UserAbortType abort_type, |
352 NotifyAbortAllLoadsWithTimestamp(abort_type, user_initiated, | 381 UserInitiatedInfo user_initiated_info) { |
| 382 NotifyAbortAllLoadsWithTimestamp(abort_type, user_initiated_info, |
353 base::TimeTicks::Now(), true); | 383 base::TimeTicks::Now(), true); |
354 } | 384 } |
355 | 385 |
356 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( | 386 void MetricsWebContentsObserver::NotifyAbortAllLoadsWithTimestamp( |
357 UserAbortType abort_type, | 387 UserAbortType abort_type, |
358 bool user_initiated, | 388 UserInitiatedInfo user_initiated_info, |
359 base::TimeTicks timestamp, | 389 base::TimeTicks timestamp, |
360 bool is_certainly_browser_timestamp) { | 390 bool is_certainly_browser_timestamp) { |
361 if (committed_load_) { | 391 if (committed_load_) { |
362 committed_load_->NotifyAbort(abort_type, user_initiated, timestamp, | 392 committed_load_->NotifyAbort(abort_type, user_initiated_info, timestamp, |
363 is_certainly_browser_timestamp); | 393 is_certainly_browser_timestamp); |
364 } | 394 } |
365 for (const auto& kv : provisional_loads_) { | 395 for (const auto& kv : provisional_loads_) { |
366 kv.second->NotifyAbort(abort_type, user_initiated, timestamp, | 396 kv.second->NotifyAbort(abort_type, user_initiated_info, timestamp, |
367 is_certainly_browser_timestamp); | 397 is_certainly_browser_timestamp); |
368 } | 398 } |
369 for (const auto& tracker : aborted_provisional_loads_) { | 399 for (const auto& tracker : aborted_provisional_loads_) { |
370 if (tracker->IsLikelyProvisionalAbort(timestamp)) { | 400 if (tracker->IsLikelyProvisionalAbort(timestamp)) { |
371 tracker->UpdateAbort(abort_type, user_initiated, timestamp, | 401 tracker->UpdateAbort(abort_type, user_initiated_info, timestamp, |
372 is_certainly_browser_timestamp); | 402 is_certainly_browser_timestamp); |
373 } | 403 } |
374 } | 404 } |
375 aborted_provisional_loads_.clear(); | 405 aborted_provisional_loads_.clear(); |
376 } | 406 } |
377 | 407 |
378 std::unique_ptr<PageLoadTracker> | 408 std::unique_ptr<PageLoadTracker> |
379 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( | 409 MetricsWebContentsObserver::NotifyAbortedProvisionalLoadsNewNavigation( |
380 content::NavigationHandle* new_navigation) { | 410 content::NavigationHandle* new_navigation, |
| 411 UserInitiatedInfo user_initiated_info) { |
381 // If there are multiple aborted loads that can be attributed to this one, | 412 // If there are multiple aborted loads that can be attributed to this one, |
382 // just count the latest one for simplicity. Other loads will fall into the | 413 // just count the latest one for simplicity. Other loads will fall into the |
383 // OTHER bucket, though there shouldn't be very many. | 414 // OTHER bucket, though there shouldn't be very many. |
384 if (aborted_provisional_loads_.size() == 0) | 415 if (aborted_provisional_loads_.size() == 0) |
385 return nullptr; | 416 return nullptr; |
386 if (aborted_provisional_loads_.size() > 1) | 417 if (aborted_provisional_loads_.size() > 1) |
387 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); | 418 RecordInternalError(ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS); |
388 | 419 |
389 std::unique_ptr<PageLoadTracker> last_aborted_load = | 420 std::unique_ptr<PageLoadTracker> last_aborted_load = |
390 std::move(aborted_provisional_loads_.back()); | 421 std::move(aborted_provisional_loads_.back()); |
391 aborted_provisional_loads_.pop_back(); | 422 aborted_provisional_loads_.pop_back(); |
392 | 423 |
393 base::TimeTicks timestamp = new_navigation->NavigationStart(); | 424 base::TimeTicks timestamp = new_navigation->NavigationStart(); |
394 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) { | 425 if (last_aborted_load->IsLikelyProvisionalAbort(timestamp)) { |
395 last_aborted_load->UpdateAbort( | 426 last_aborted_load->UpdateAbort( |
396 AbortTypeForPageTransition(new_navigation->GetPageTransition()), | 427 AbortTypeForPageTransition(new_navigation->GetPageTransition()), |
397 IsNavigationUserInitiated(new_navigation), timestamp, false); | 428 user_initiated_info, timestamp, false); |
398 } | 429 } |
399 | 430 |
400 aborted_provisional_loads_.clear(); | 431 aborted_provisional_loads_.clear(); |
401 return last_aborted_load; | 432 return last_aborted_load; |
402 } | 433 } |
403 | 434 |
404 void MetricsWebContentsObserver::OnTimingUpdated( | 435 void MetricsWebContentsObserver::OnTimingUpdated( |
405 content::RenderFrameHost* render_frame_host, | 436 content::RenderFrameHost* render_frame_host, |
406 const PageLoadTiming& timing, | 437 const PageLoadTiming& timing, |
407 const PageLoadMetadata& metadata) { | 438 const PageLoadMetadata& metadata) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 content::NavigationHandle* navigation_handle) const { | 473 content::NavigationHandle* navigation_handle) const { |
443 DCHECK(navigation_handle->IsInMainFrame()); | 474 DCHECK(navigation_handle->IsInMainFrame()); |
444 DCHECK(!navigation_handle->HasCommitted() || | 475 DCHECK(!navigation_handle->HasCommitted() || |
445 !navigation_handle->IsSamePage()); | 476 !navigation_handle->IsSamePage()); |
446 | 477 |
447 return BrowserPageTrackDecider(embedder_interface_.get(), web_contents(), | 478 return BrowserPageTrackDecider(embedder_interface_.get(), web_contents(), |
448 navigation_handle).ShouldTrack(); | 479 navigation_handle).ShouldTrack(); |
449 } | 480 } |
450 | 481 |
451 } // namespace page_load_metrics | 482 } // namespace page_load_metrics |
OLD | NEW |