OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/observers/ads_page_load_metrics_obser ver.h" | 5 #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_obser ver.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/test/histogram_tester.h" | 10 #include "base/test/histogram_tester.h" |
11 #include "chrome/browser/page_load_metrics/metrics_web_contents_observer.h" | |
11 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_ test_harness.h" | 12 #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_ test_harness.h" |
12 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" | 13 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" |
13 #include "chrome/browser/page_load_metrics/page_load_tracker.h" | 14 #include "chrome/browser/page_load_metrics/page_load_tracker.h" |
15 #include "content/public/browser/global_request_id.h" | |
16 #include "content/public/browser/navigation_handle.h" | |
17 #include "content/public/browser/navigation_throttle.h" | |
14 #include "content/public/browser/render_frame_host.h" | 18 #include "content/public/browser/render_frame_host.h" |
15 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" |
20 #include "content/public/browser/web_contents_observer.h" | |
16 #include "content/public/common/resource_type.h" | 21 #include "content/public/common/resource_type.h" |
17 #include "content/public/test/navigation_simulator.h" | 22 #include "content/public/test/navigation_simulator.h" |
18 #include "content/public/test/test_renderer_host.h" | 23 #include "content/public/test/test_renderer_host.h" |
19 #include "url/gurl.h" | 24 #include "url/gurl.h" |
20 | 25 |
21 using content::RenderFrameHost; | 26 using content::RenderFrameHost; |
22 using content::RenderFrameHostTester; | 27 using content::RenderFrameHostTester; |
23 using content::NavigationSimulator; | 28 using content::NavigationSimulator; |
24 | 29 |
25 namespace { | 30 namespace { |
26 | 31 |
27 enum class ResourceCached { NOT_CACHED, CACHED }; | 32 enum class ResourceCached { NOT_CACHED, CACHED }; |
28 enum class FrameType { AD = 0, NON_AD }; | 33 enum class FrameType { AD = 0, NON_AD }; |
29 | 34 |
30 const char kAdUrl[] = "https://tpc.googlesyndication.com/safeframe/1"; | 35 const char kAdUrl[] = "https://tpc.googlesyndication.com/safeframe/1"; |
31 const char kNonAdUrl[] = "https://foo.com/"; | 36 const char kNonAdUrl[] = "https://foo.com/"; |
32 const char kNonAdUrl2[] = "https://bar.com/"; | 37 const char kNonAdUrl2[] = "https://bar.com/"; |
33 | 38 |
34 const char kAdName[] = "google_ads_iframe_1"; | 39 const char kAdName[] = "google_ads_iframe_1"; |
35 const char kNonAdName[] = "foo"; | 40 const char kNonAdName[] = "foo"; |
36 | 41 |
42 class DelayWillProcessResponseObserver; | |
43 | |
44 // Delays WillProcessResponse until the caller tells it to cancel. | |
Charlie Harrison
2017/05/17 18:54:51
Would you add a TODO(csharrison) to add this to th
jkarlin
2017/05/18 13:50:13
Done.
| |
45 class DelayWillProcessResponseThrottle : public content::NavigationThrottle { | |
46 public: | |
47 explicit DelayWillProcessResponseThrottle( | |
48 content::NavigationHandle* navigation_handle) | |
49 : NavigationThrottle(navigation_handle) {} | |
50 | |
51 // NavigationThrottle overrides | |
Charlie Harrison
2017/05/17 18:54:50
// content::NavigationThrottle:
jkarlin
2017/05/18 13:50:13
Done.
| |
52 ThrottleCheckResult WillProcessResponse() override { | |
53 return NavigationThrottle::DEFER; | |
54 } | |
55 const char* GetNameForLogging() override { | |
56 return "DelayWillProcessResponseThrottle"; | |
57 } | |
58 | |
59 void CancelDeferredNavigation() { | |
60 navigation_handle()->CancelDeferredNavigation(NavigationThrottle::CANCEL); | |
61 } | |
62 | |
63 content::GlobalRequestID GetGlobalRequestID() const { | |
64 return navigation_handle()->GetGlobalRequestID(); | |
65 } | |
66 | |
67 private: | |
68 DISALLOW_COPY_AND_ASSIGN(DelayWillProcessResponseThrottle); | |
69 }; | |
70 | |
71 // Adds a navigation throttle to the navigation which delays | |
72 // WillProcessResponse. | |
73 class DelayWillProcessResponseObserver : public content::WebContentsObserver { | |
74 public: | |
75 explicit DelayWillProcessResponseObserver(content::WebContents* contents) | |
76 : WebContentsObserver(contents), throttle_(nullptr) {} | |
Charlie Harrison
2017/05/17 18:54:50
Hm why don't you need content:: prefix to WebConte
Charlie Harrison
2017/05/17 18:54:50
Don't need to set throttle_ to nullptr here since
jkarlin
2017/05/18 13:50:13
Done.
jkarlin
2017/05/18 13:50:13
I have no idea. Added for clarity.
| |
77 | |
78 // WebContentsObserver override | |
Charlie Harrison
2017/05/17 18:54:50
// content::WebContentsObserver:
jkarlin
2017/05/18 13:50:13
Done.
| |
79 void DidStartNavigation( | |
80 content::NavigationHandle* navigation_handle) override { | |
81 std::unique_ptr<content::NavigationThrottle> delay_throttle = | |
82 base::MakeUnique<DelayWillProcessResponseThrottle>(navigation_handle); | |
83 throttle_ = | |
84 static_cast<DelayWillProcessResponseThrottle*>(delay_throttle.get()); | |
85 navigation_handle->RegisterThrottleForTesting(std::move(delay_throttle)); | |
86 } | |
87 | |
88 DelayWillProcessResponseThrottle* throttle() const { return throttle_; } | |
89 | |
90 private: | |
91 DelayWillProcessResponseThrottle* throttle_ = nullptr; | |
92 content::GlobalRequestID global_request_id_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(DelayWillProcessResponseObserver); | |
95 }; | |
96 | |
97 void LoadResourceForMainFrameAndResume( | |
Charlie Harrison
2017/05/17 18:54:50
Why not include this as a method in the delay obse
jkarlin
2017/05/18 13:50:13
Done.
| |
98 page_load_metrics::MetricsWebContentsObserver* observer, | |
99 DelayWillProcessResponseThrottle* throttle) { | |
100 // Load a resource for the main frame before it commits. | |
101 content::NavigationHandle* navigation_handle = throttle->navigation_handle(); | |
102 | |
103 observer->OnRequestComplete( | |
104 GURL(kNonAdUrl), | |
105 navigation_handle->GetRenderFrameHost()->GetFrameTreeNodeId(), | |
106 navigation_handle->GetGlobalRequestID(), | |
107 content::RESOURCE_TYPE_MAIN_FRAME, false /* was_cached */, | |
108 nullptr /* data_reduction_proxy */, 10 * 1024 /* raw_body_bytes */, | |
109 0 /* original_network_content_length */, base::TimeTicks::Now()); | |
110 | |
111 throttle->CancelDeferredNavigation(); | |
112 } | |
113 | |
37 } // namespace | 114 } // namespace |
38 | 115 |
39 class AdsPageLoadMetricsObserverTest | 116 class AdsPageLoadMetricsObserverTest |
40 : public page_load_metrics::PageLoadMetricsObserverTestHarness { | 117 : public page_load_metrics::PageLoadMetricsObserverTestHarness { |
41 public: | 118 public: |
42 AdsPageLoadMetricsObserverTest() {} | 119 AdsPageLoadMetricsObserverTest() {} |
43 | 120 |
44 // Returns the final RenderFrameHost after navigation commits. | 121 // Returns the final RenderFrameHost after navigation commits. |
45 RenderFrameHost* NavigateFrame(const std::string& url, | 122 RenderFrameHost* NavigateFrame(const std::string& url, |
46 content::RenderFrameHost* frame) { | 123 content::RenderFrameHost* frame) { |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
598 | 675 |
599 // Test that a resource loaded into an unknown frame doesn't cause any | 676 // Test that a resource loaded into an unknown frame doesn't cause any |
600 // issues. | 677 // issues. |
601 histogram_tester().ExpectTotalCount( | 678 histogram_tester().ExpectTotalCount( |
602 "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0); | 679 "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", 0); |
603 LoadResource(child_of_subframe, ResourceCached::NOT_CACHED, 10); | 680 LoadResource(child_of_subframe, ResourceCached::NOT_CACHED, 10); |
604 histogram_tester().ExpectBucketCount( | 681 histogram_tester().ExpectBucketCount( |
605 "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", | 682 "PageLoad.Clients.Ads.Google.ResourceTypeWhenNoFrameFound", |
606 content::RESOURCE_TYPE_SUB_FRAME, 1); | 683 content::RESOURCE_TYPE_SUB_FRAME, 1); |
607 } | 684 } |
685 | |
686 // Make sure that ads histograms aren't recorded if the tracker never commits | |
687 // (see https://crbug.com/723219). | |
688 TEST_F(AdsPageLoadMetricsObserverTest, NoHistogramWithoutCommit) { | |
689 // Once the metrics observer has the GlobalRequestID, throttle. | |
690 DelayWillProcessResponseObserver delay_observer(web_contents()); | |
691 | |
692 // Start main-frame navigation | |
693 auto navigation_simulator = NavigationSimulator::CreateRendererInitiated( | |
694 GURL(kNonAdUrl), web_contents()->GetMainFrame()); | |
695 navigation_simulator->Start(); | |
696 | |
697 // This will be run once WillProcessResponse defers and the navigation | |
698 // simulator runs the message loop waiting for the throttles to finish. | |
699 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
700 FROM_HERE, base::Bind(&LoadResourceForMainFrameAndResume, observer(), | |
701 delay_observer.throttle())); | |
702 | |
703 // The commit will defer after calling WillProcessNavigationResponse, it | |
704 // will load a resource, and then the throttle will cancel the commit. | |
705 navigation_simulator->Commit(); | |
706 | |
707 // There shouldn't be any histograms for an aborted main frame. | |
708 EXPECT_EQ(0u, histogram_tester() | |
709 .GetTotalCountsForPrefix("PageLoad.Clients.Ads.") | |
710 .size()); | |
711 } | |
OLD | NEW |