OLD | NEW |
| (Empty) |
1 // Copyright (c) 2015 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 "components/page_load_metrics/browser/metrics_web_contents_observer.h" | |
6 | |
7 #include <memory> | |
8 #include <vector> | |
9 | |
10 #include "base/macros.h" | |
11 #include "base/memory/ptr_util.h" | |
12 #include "base/process/kill.h" | |
13 #include "base/test/histogram_tester.h" | |
14 #include "base/time/time.h" | |
15 #include "components/page_load_metrics/browser/page_load_metrics_observer.h" | |
16 #include "components/page_load_metrics/common/page_load_metrics_messages.h" | |
17 #include "content/public/browser/navigation_handle.h" | |
18 #include "content/public/browser/render_frame_host.h" | |
19 #include "content/public/test/test_renderer_host.h" | |
20 #include "content/public/test/web_contents_tester.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 #include "url/gurl.h" | |
23 | |
24 namespace page_load_metrics { | |
25 | |
26 namespace { | |
27 | |
28 const char kDefaultTestUrl[] = "https://google.com/"; | |
29 const char kDefaultTestUrlAnchor[] = "https://google.com/#samepage"; | |
30 const char kDefaultTestUrl2[] = "https://whatever.com/"; | |
31 | |
32 // Simple PageLoadMetricsObserver that copies observed PageLoadTimings into the | |
33 // provided std::vector, so they can be analyzed by unit tests. | |
34 class TestPageLoadMetricsObserver : public PageLoadMetricsObserver { | |
35 public: | |
36 explicit TestPageLoadMetricsObserver( | |
37 std::vector<PageLoadTiming>* updated_timings, | |
38 std::vector<PageLoadTiming>* complete_timings, | |
39 std::vector<GURL>* observed_committed_urls) | |
40 : updated_timings_(updated_timings), | |
41 complete_timings_(complete_timings), | |
42 observed_committed_urls_(observed_committed_urls) {} | |
43 | |
44 void OnStart(content::NavigationHandle* navigation_handle, | |
45 const GURL& currently_committed_url, | |
46 bool started_in_foreground) override { | |
47 observed_committed_urls_->push_back(currently_committed_url); | |
48 } | |
49 | |
50 void OnTimingUpdate(const PageLoadTiming& timing, | |
51 const PageLoadExtraInfo& extra_info) override { | |
52 updated_timings_->push_back(timing); | |
53 } | |
54 | |
55 void OnComplete(const PageLoadTiming& timing, | |
56 const PageLoadExtraInfo& extra_info) override { | |
57 complete_timings_->push_back(timing); | |
58 } | |
59 | |
60 private: | |
61 std::vector<PageLoadTiming>* const updated_timings_; | |
62 std::vector<PageLoadTiming>* const complete_timings_; | |
63 std::vector<GURL>* const observed_committed_urls_; | |
64 }; | |
65 | |
66 class TestPageLoadMetricsEmbedderInterface | |
67 : public PageLoadMetricsEmbedderInterface { | |
68 public: | |
69 TestPageLoadMetricsEmbedderInterface() | |
70 : is_prerendering_(false), is_ntp_(false) {} | |
71 | |
72 bool IsPrerendering(content::WebContents* web_contents) override { | |
73 return is_prerendering_; | |
74 } | |
75 bool IsNewTabPageUrl(const GURL& url) override { return is_ntp_; } | |
76 void set_is_prerendering(bool is_prerendering) { | |
77 is_prerendering_ = is_prerendering; | |
78 } | |
79 void set_is_ntp(bool is_ntp) { is_ntp_ = is_ntp; } | |
80 void RegisterObservers(PageLoadTracker* tracker) override { | |
81 tracker->AddObserver(base::WrapUnique(new TestPageLoadMetricsObserver( | |
82 &updated_timings_, &complete_timings_, &observed_committed_urls_))); | |
83 } | |
84 const std::vector<PageLoadTiming>& updated_timings() const { | |
85 return updated_timings_; | |
86 } | |
87 const std::vector<PageLoadTiming>& complete_timings() const { | |
88 return complete_timings_; | |
89 } | |
90 | |
91 // currently_committed_urls passed to OnStart(). | |
92 const std::vector<GURL>& observed_committed_urls_from_on_start() const { | |
93 return observed_committed_urls_; | |
94 } | |
95 | |
96 private: | |
97 std::vector<PageLoadTiming> updated_timings_; | |
98 std::vector<PageLoadTiming> complete_timings_; | |
99 std::vector<GURL> observed_committed_urls_; | |
100 bool is_prerendering_; | |
101 bool is_ntp_; | |
102 }; | |
103 | |
104 } // namespace | |
105 | |
106 class MetricsWebContentsObserverTest | |
107 : public content::RenderViewHostTestHarness { | |
108 public: | |
109 MetricsWebContentsObserverTest() : num_errors_(0) {} | |
110 | |
111 void SetUp() override { | |
112 RenderViewHostTestHarness::SetUp(); | |
113 AttachObserver(); | |
114 } | |
115 | |
116 void SimulateTimingUpdate(const PageLoadTiming& timing) { | |
117 SimulateTimingUpdate(timing, web_contents()->GetMainFrame()); | |
118 } | |
119 | |
120 void SimulateTimingUpdate(const PageLoadTiming& timing, | |
121 content::RenderFrameHost* render_frame_host) { | |
122 ASSERT_TRUE(observer_->OnMessageReceived( | |
123 PageLoadMetricsMsg_TimingUpdated(observer_->routing_id(), timing, | |
124 PageLoadMetadata()), | |
125 render_frame_host)); | |
126 } | |
127 | |
128 void AttachObserver() { | |
129 embedder_interface_ = new TestPageLoadMetricsEmbedderInterface(); | |
130 observer_.reset(new MetricsWebContentsObserver( | |
131 web_contents(), base::WrapUnique(embedder_interface_))); | |
132 observer_->WasShown(); | |
133 } | |
134 | |
135 void CheckErrorEvent(InternalErrorLoadEvent error, int count) { | |
136 histogram_tester_.ExpectBucketCount(internal::kErrorEvents, error, count); | |
137 num_errors_ += count; | |
138 } | |
139 | |
140 void CheckTotalErrorEvents() { | |
141 histogram_tester_.ExpectTotalCount(internal::kErrorEvents, num_errors_); | |
142 } | |
143 | |
144 void CheckNoErrorEvents() { | |
145 histogram_tester_.ExpectTotalCount(internal::kErrorEvents, 0); | |
146 } | |
147 | |
148 int CountEmptyCompleteTimingReported() { | |
149 int empty = 0; | |
150 for (const auto& timing : embedder_interface_->complete_timings()) { | |
151 if (timing.IsEmpty()) | |
152 ++empty; | |
153 } | |
154 return empty; | |
155 } | |
156 | |
157 int CountCompleteTimingReported() { | |
158 return embedder_interface_->complete_timings().size(); | |
159 } | |
160 int CountUpdatedTimingReported() { | |
161 return embedder_interface_->updated_timings().size(); | |
162 } | |
163 | |
164 const std::vector<GURL>& observed_committed_urls_from_on_start() const { | |
165 return embedder_interface_->observed_committed_urls_from_on_start(); | |
166 } | |
167 | |
168 protected: | |
169 base::HistogramTester histogram_tester_; | |
170 TestPageLoadMetricsEmbedderInterface* embedder_interface_; | |
171 std::unique_ptr<MetricsWebContentsObserver> observer_; | |
172 | |
173 private: | |
174 int num_errors_; | |
175 | |
176 DISALLOW_COPY_AND_ASSIGN(MetricsWebContentsObserverTest); | |
177 }; | |
178 | |
179 TEST_F(MetricsWebContentsObserverTest, SuccessfulMainFrameNavigation) { | |
180 PageLoadTiming timing; | |
181 timing.navigation_start = base::Time::FromDoubleT(1); | |
182 timing.response_start = base::TimeDelta::FromMilliseconds(2); | |
183 | |
184 content::WebContentsTester* web_contents_tester = | |
185 content::WebContentsTester::For(web_contents()); | |
186 | |
187 ASSERT_TRUE(observed_committed_urls_from_on_start().empty()); | |
188 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
189 ASSERT_EQ(1u, observed_committed_urls_from_on_start().size()); | |
190 ASSERT_TRUE(observed_committed_urls_from_on_start().at(0).is_empty()); | |
191 | |
192 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
193 SimulateTimingUpdate(timing); | |
194 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
195 ASSERT_EQ(0, CountCompleteTimingReported()); | |
196 | |
197 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
198 ASSERT_EQ(1, CountCompleteTimingReported()); | |
199 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | |
200 ASSERT_EQ(2u, observed_committed_urls_from_on_start().size()); | |
201 ASSERT_EQ(kDefaultTestUrl, | |
202 observed_committed_urls_from_on_start().at(1).spec()); | |
203 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
204 | |
205 CheckNoErrorEvents(); | |
206 } | |
207 | |
208 TEST_F(MetricsWebContentsObserverTest, NotInMainFrame) { | |
209 PageLoadTiming timing; | |
210 timing.navigation_start = base::Time::FromDoubleT(1); | |
211 | |
212 content::WebContentsTester* web_contents_tester = | |
213 content::WebContentsTester::For(web_contents()); | |
214 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
215 | |
216 content::RenderFrameHostTester* rfh_tester = | |
217 content::RenderFrameHostTester::For(main_rfh()); | |
218 content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | |
219 | |
220 content::RenderFrameHostTester* subframe_tester = | |
221 content::RenderFrameHostTester::For(subframe); | |
222 subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | |
223 subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | |
224 SimulateTimingUpdate(timing, subframe); | |
225 subframe_tester->SimulateNavigationStop(); | |
226 | |
227 // Navigate again to see if the timing updated for a subframe message. | |
228 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
229 | |
230 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
231 ASSERT_EQ(1, CountCompleteTimingReported()); | |
232 ASSERT_EQ(1, CountEmptyCompleteTimingReported()); | |
233 CheckErrorEvent(ERR_IPC_FROM_WRONG_FRAME, 1); | |
234 CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 1); | |
235 CheckTotalErrorEvents(); | |
236 } | |
237 | |
238 TEST_F(MetricsWebContentsObserverTest, SamePageNoTrigger) { | |
239 PageLoadTiming timing; | |
240 timing.navigation_start = base::Time::FromDoubleT(1); | |
241 | |
242 content::WebContentsTester* web_contents_tester = | |
243 content::WebContentsTester::For(web_contents()); | |
244 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
245 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
246 SimulateTimingUpdate(timing); | |
247 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
248 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrlAnchor)); | |
249 // Send the same timing update. The original tracker for kDefaultTestUrl | |
250 // should dedup the update, and the tracker for kDefaultTestUrlAnchor should | |
251 // have been destroyed as a result of its being a same page navigation, so | |
252 // CountUpdatedTimingReported() should continue to return 1. | |
253 SimulateTimingUpdate(timing); | |
254 | |
255 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
256 ASSERT_EQ(0, CountCompleteTimingReported()); | |
257 | |
258 // Navigate again to force histogram logging. | |
259 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
260 | |
261 // A same page navigation shouldn't trigger logging UMA for the original. | |
262 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
263 ASSERT_EQ(1, CountCompleteTimingReported()); | |
264 ASSERT_EQ(0, CountEmptyCompleteTimingReported()); | |
265 CheckNoErrorEvents(); | |
266 } | |
267 | |
268 TEST_F(MetricsWebContentsObserverTest, DontLogPrerender) { | |
269 PageLoadTiming timing; | |
270 timing.navigation_start = base::Time::FromDoubleT(1); | |
271 | |
272 content::WebContentsTester* web_contents_tester = | |
273 content::WebContentsTester::For(web_contents()); | |
274 embedder_interface_->set_is_prerendering(true); | |
275 | |
276 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
277 SimulateTimingUpdate(timing); | |
278 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
279 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
280 ASSERT_EQ(0, CountCompleteTimingReported()); | |
281 CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | |
282 CheckTotalErrorEvents(); | |
283 } | |
284 | |
285 TEST_F(MetricsWebContentsObserverTest, DontLogNewTabPage) { | |
286 PageLoadTiming timing; | |
287 timing.navigation_start = base::Time::FromDoubleT(1); | |
288 | |
289 content::WebContentsTester* web_contents_tester = | |
290 content::WebContentsTester::For(web_contents()); | |
291 embedder_interface_->set_is_ntp(true); | |
292 | |
293 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
294 SimulateTimingUpdate(timing); | |
295 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
296 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
297 ASSERT_EQ(0, CountCompleteTimingReported()); | |
298 CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | |
299 CheckTotalErrorEvents(); | |
300 } | |
301 | |
302 TEST_F(MetricsWebContentsObserverTest, DontLogIrrelevantNavigation) { | |
303 PageLoadTiming timing; | |
304 timing.navigation_start = base::Time::FromDoubleT(10); | |
305 | |
306 content::WebContentsTester* web_contents_tester = | |
307 content::WebContentsTester::For(web_contents()); | |
308 | |
309 GURL about_blank_url = GURL("about:blank"); | |
310 web_contents_tester->NavigateAndCommit(about_blank_url); | |
311 SimulateTimingUpdate(timing); | |
312 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
313 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
314 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
315 ASSERT_EQ(0, CountCompleteTimingReported()); | |
316 | |
317 CheckErrorEvent(ERR_IPC_FROM_BAD_URL_SCHEME, 1); | |
318 CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | |
319 CheckTotalErrorEvents(); | |
320 } | |
321 | |
322 TEST_F(MetricsWebContentsObserverTest, NotInMainError) { | |
323 PageLoadTiming timing; | |
324 timing.navigation_start = base::Time::FromDoubleT(1); | |
325 | |
326 content::WebContentsTester* web_contents_tester = | |
327 content::WebContentsTester::For(web_contents()); | |
328 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
329 | |
330 content::RenderFrameHostTester* rfh_tester = | |
331 content::RenderFrameHostTester::For(main_rfh()); | |
332 content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe"); | |
333 | |
334 content::RenderFrameHostTester* subframe_tester = | |
335 content::RenderFrameHostTester::For(subframe); | |
336 subframe_tester->SimulateNavigationStart(GURL(kDefaultTestUrl2)); | |
337 subframe_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl2)); | |
338 SimulateTimingUpdate(timing, subframe); | |
339 CheckErrorEvent(ERR_IPC_FROM_WRONG_FRAME, 1); | |
340 CheckTotalErrorEvents(); | |
341 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
342 ASSERT_EQ(0, CountCompleteTimingReported()); | |
343 } | |
344 | |
345 TEST_F(MetricsWebContentsObserverTest, BadIPC) { | |
346 PageLoadTiming timing; | |
347 timing.navigation_start = base::Time::FromDoubleT(10); | |
348 PageLoadTiming timing2; | |
349 timing2.navigation_start = base::Time::FromDoubleT(100); | |
350 | |
351 content::WebContentsTester* web_contents_tester = | |
352 content::WebContentsTester::For(web_contents()); | |
353 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
354 | |
355 SimulateTimingUpdate(timing); | |
356 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
357 SimulateTimingUpdate(timing2); | |
358 ASSERT_EQ(1, CountUpdatedTimingReported()); | |
359 | |
360 CheckErrorEvent(ERR_BAD_TIMING_IPC, 1); | |
361 CheckTotalErrorEvents(); | |
362 } | |
363 | |
364 TEST_F(MetricsWebContentsObserverTest, ObservePartialNavigation) { | |
365 // Delete the observer for this test, add it once the navigation has started. | |
366 observer_.reset(); | |
367 PageLoadTiming timing; | |
368 timing.navigation_start = base::Time::FromDoubleT(10); | |
369 | |
370 content::WebContentsTester* web_contents_tester = | |
371 content::WebContentsTester::For(web_contents()); | |
372 content::RenderFrameHostTester* rfh_tester = | |
373 content::RenderFrameHostTester::For(main_rfh()); | |
374 | |
375 // Start the navigation, then start observing the web contents. This used to | |
376 // crash us. Make sure we bail out and don't log histograms. | |
377 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
378 AttachObserver(); | |
379 rfh_tester->SimulateNavigationCommit(GURL(kDefaultTestUrl)); | |
380 | |
381 SimulateTimingUpdate(timing); | |
382 | |
383 // Navigate again to force histogram logging. | |
384 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
385 ASSERT_EQ(0, CountCompleteTimingReported()); | |
386 ASSERT_EQ(0, CountUpdatedTimingReported()); | |
387 CheckErrorEvent(ERR_IPC_WITH_NO_RELEVANT_LOAD, 1); | |
388 CheckTotalErrorEvents(); | |
389 } | |
390 | |
391 TEST_F(MetricsWebContentsObserverTest, DontLogAbortChains) { | |
392 NavigateAndCommit(GURL(kDefaultTestUrl)); | |
393 NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
394 NavigateAndCommit(GURL(kDefaultTestUrl)); | |
395 histogram_tester_.ExpectTotalCount(internal::kAbortChainSizeNewNavigation, 0); | |
396 CheckErrorEvent(ERR_NO_IPCS_RECEIVED, 2); | |
397 CheckTotalErrorEvents(); | |
398 } | |
399 | |
400 TEST_F(MetricsWebContentsObserverTest, LogAbortChains) { | |
401 content::WebContentsTester* web_contents_tester = | |
402 content::WebContentsTester::For(web_contents()); | |
403 content::RenderFrameHostTester* rfh_tester = | |
404 content::RenderFrameHostTester::For(main_rfh()); | |
405 // Start and abort three loads before one finally commits. | |
406 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
407 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
408 rfh_tester->SimulateNavigationStop(); | |
409 | |
410 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl2)); | |
411 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl2), net::ERR_ABORTED); | |
412 rfh_tester->SimulateNavigationStop(); | |
413 | |
414 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
415 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
416 rfh_tester->SimulateNavigationStop(); | |
417 | |
418 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl2)); | |
419 histogram_tester_.ExpectTotalCount(internal::kAbortChainSizeNewNavigation, 1); | |
420 histogram_tester_.ExpectBucketCount(internal::kAbortChainSizeNewNavigation, 3, | |
421 1); | |
422 CheckNoErrorEvents(); | |
423 } | |
424 | |
425 TEST_F(MetricsWebContentsObserverTest, LogAbortChainsSameURL) { | |
426 content::WebContentsTester* web_contents_tester = | |
427 content::WebContentsTester::For(web_contents()); | |
428 content::RenderFrameHostTester* rfh_tester = | |
429 content::RenderFrameHostTester::For(main_rfh()); | |
430 // Start and abort three loads before one finally commits. | |
431 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
432 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
433 rfh_tester->SimulateNavigationStop(); | |
434 | |
435 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
436 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
437 rfh_tester->SimulateNavigationStop(); | |
438 | |
439 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
440 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
441 rfh_tester->SimulateNavigationStop(); | |
442 | |
443 web_contents_tester->NavigateAndCommit(GURL(kDefaultTestUrl)); | |
444 histogram_tester_.ExpectTotalCount(internal::kAbortChainSizeNewNavigation, 1); | |
445 histogram_tester_.ExpectBucketCount(internal::kAbortChainSizeNewNavigation, 3, | |
446 1); | |
447 histogram_tester_.ExpectTotalCount(internal::kAbortChainSizeSameURL, 1); | |
448 histogram_tester_.ExpectBucketCount(internal::kAbortChainSizeSameURL, 3, 1); | |
449 } | |
450 | |
451 TEST_F(MetricsWebContentsObserverTest, LogAbortChainsNoCommit) { | |
452 content::WebContentsTester* web_contents_tester = | |
453 content::WebContentsTester::For(web_contents()); | |
454 content::RenderFrameHostTester* rfh_tester = | |
455 content::RenderFrameHostTester::For(main_rfh()); | |
456 // Start and abort three loads before one finally commits. | |
457 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
458 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
459 rfh_tester->SimulateNavigationStop(); | |
460 | |
461 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl2)); | |
462 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl2), net::ERR_ABORTED); | |
463 rfh_tester->SimulateNavigationStop(); | |
464 | |
465 web_contents_tester->StartNavigation(GURL(kDefaultTestUrl)); | |
466 rfh_tester->SimulateNavigationError(GURL(kDefaultTestUrl), net::ERR_ABORTED); | |
467 rfh_tester->SimulateNavigationStop(); | |
468 | |
469 web_contents()->Stop(); | |
470 | |
471 histogram_tester_.ExpectTotalCount(internal::kAbortChainSizeNoCommit, 1); | |
472 histogram_tester_.ExpectBucketCount(internal::kAbortChainSizeNoCommit, 3, | |
473 1); | |
474 } | |
475 | |
476 } // namespace page_load_metrics | |
OLD | NEW |