1 // Copyright 2018 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 "base/task/post_task.h"
6 #include "build/build_config.h"
7 #include "chrome/browser/ui/browser.h"
8 #include "chrome/test/base/in_process_browser_test.h"
9 #include "components/ukm/test_ukm_recorder.h"
10 #include "content/public/browser/navigation_controller.h"
11 #include "content/public/test/browser_test.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/test_frame_navigation_observer.h"
14 #include "net/dns/mock_host_resolver.h"
15 #include "services/metrics/public/cpp/ukm_builders.h"
16 #include "services/metrics/public/cpp/ukm_source.h"
17
18 namespace chrome {
19
20 namespace {
21
22 class AutoplayMetricsBrowserTest : public InProcessBrowserTest {
23 public:
24 using Entry = ukm::builders::Media_Autoplay_Attempt;
25 using CreatedEntry = ukm::builders::DocumentCreated;
26
SetUpOnMainThread()27 void SetUpOnMainThread() override {
28 host_resolver()->AddRule("*", "127.0.0.1");
29 content::SetupCrossSiteRedirector(embedded_test_server());
30 ASSERT_TRUE(embedded_test_server()->Start());
31 }
32
TryAutoplay(ukm::TestUkmRecorder & ukm_recorder,const content::ToRenderFrameHost & adapter)33 void TryAutoplay(ukm::TestUkmRecorder& ukm_recorder,
34 const content::ToRenderFrameHost& adapter) {
35 base::RunLoop run_loop;
36 ukm_recorder.SetOnAddEntryCallback(Entry::kEntryName,
37 run_loop.QuitClosure());
38 EXPECT_TRUE(ExecuteScriptWithoutUserGesture(adapter.render_frame_host(),
39 "tryPlayback();"));
40 run_loop.Run();
41 }
42
NavigateFrameAndWait(content::RenderFrameHost * rfh,const GURL & url)43 void NavigateFrameAndWait(content::RenderFrameHost* rfh, const GURL& url) {
44 content::TestFrameNavigationObserver observer(rfh);
45 content::NavigationController::LoadURLParams params(url);
46 params.transition_type = ui::PAGE_TRANSITION_LINK;
47 params.frame_tree_node_id = rfh->GetFrameTreeNodeId();
48 content::WebContents::FromRenderFrameHost(rfh)
49 ->GetController()
50 .LoadURLWithParams(params);
51 observer.Wait();
52 }
53
web_contents() const54 content::WebContents* web_contents() const {
55 return browser()->tab_strip_model()->GetActiveWebContents();
56 }
57
first_child() const58 content::RenderFrameHost* first_child() const {
59 return web_contents()->GetAllFrames()[1];
60 }
61
second_child() const62 content::RenderFrameHost* second_child() const {
63 return web_contents()->GetAllFrames()[2];
64 }
65 };
66
67 // Flaky on various platforms. https://crbug.com/1101841
68 #if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS)
69 #define MAYBE_RecordAutoplayAttemptUkm DISABLED_RecordAutoplayAttemptUkm
70 #else
71 #define MAYBE_RecordAutoplayAttemptUkm RecordAutoplayAttemptUkm
72 #endif
IN_PROC_BROWSER_TEST_F(AutoplayMetricsBrowserTest,MAYBE_RecordAutoplayAttemptUkm)73 IN_PROC_BROWSER_TEST_F(AutoplayMetricsBrowserTest,
74 MAYBE_RecordAutoplayAttemptUkm) {
75 ukm::TestAutoSetUkmRecorder test_ukm_recorder;
76 GURL main_url(embedded_test_server()->GetURL("example.com",
77 "/media/autoplay_iframe.html"));
78 GURL foo_url(
79 embedded_test_server()->GetURL("foo.com", "/media/autoplay_iframe.html"));
80 GURL bar_url(
81 embedded_test_server()->GetURL("bar.com", "/media/autoplay_iframe.html"));
82
83 // Navigate main frame, try play.
84 NavigateFrameAndWait(web_contents()->GetMainFrame(), main_url);
85 TryAutoplay(test_ukm_recorder, web_contents());
86
87 // Check that we recorded a UKM event using the main frame URL.
88 {
89 auto ukm_entries = test_ukm_recorder.GetEntriesByName(Entry::kEntryName);
90
91 ASSERT_EQ(1u, ukm_entries.size());
92 test_ukm_recorder.ExpectEntrySourceHasUrl(ukm_entries[0], main_url);
93 }
94
95 // Navigate sub frame, try play.
96 NavigateFrameAndWait(first_child(), foo_url);
97 TryAutoplay(test_ukm_recorder, first_child());
98
99 // Check that we recorded a UKM event that is not keyed to any URL.
100 {
101 auto ukm_entries = test_ukm_recorder.GetEntriesByName(Entry::kEntryName);
102
103 ASSERT_EQ(2u, ukm_entries.size());
104 EXPECT_FALSE(
105 test_ukm_recorder.GetSourceForSourceId(ukm_entries[1]->source_id));
106
107 // Check that a DocumentCreated entry was also created that was not keyed to
108 // any URL. However, we can use the navigation source ID to link this source
109 // to the top frame URL.
110 auto* dc_entry = test_ukm_recorder.GetDocumentCreatedEntryForSourceId(
111 ukm_entries[1]->source_id);
112 EXPECT_TRUE(dc_entry);
113 EXPECT_EQ(ukm_entries[1]->source_id, dc_entry->source_id);
114 EXPECT_FALSE(test_ukm_recorder.GetSourceForSourceId(dc_entry->source_id));
115 EXPECT_EQ(main_url,
116 test_ukm_recorder
117 .GetSourceForSourceId(*test_ukm_recorder.GetEntryMetric(
118 dc_entry, CreatedEntry::kNavigationSourceIdName))
119 ->url());
120 EXPECT_EQ(0, *test_ukm_recorder.GetEntryMetric(
121 dc_entry, CreatedEntry::kIsMainFrameName));
122 }
123
124 // Navigate sub sub frame, try play.
125 NavigateFrameAndWait(second_child(), bar_url);
126 TryAutoplay(test_ukm_recorder, second_child());
127
128 // Check that we recorded a UKM event that is not keyed to any url.
129 {
130 auto ukm_entries = test_ukm_recorder.GetEntriesByName(Entry::kEntryName);
131
132 ASSERT_EQ(3u, ukm_entries.size());
133 EXPECT_FALSE(
134 test_ukm_recorder.GetSourceForSourceId(ukm_entries[2]->source_id));
135
136 // Check that a DocumentCreated entry was also created that was not keyed to
137 // any URL. However, we can use the navigation source ID to link this source
138 // to the top frame URL.
139 auto* dc_entry = test_ukm_recorder.GetDocumentCreatedEntryForSourceId(
140 ukm_entries[2]->source_id);
141 EXPECT_TRUE(dc_entry);
142 EXPECT_EQ(ukm_entries[2]->source_id, dc_entry->source_id);
143 EXPECT_FALSE(test_ukm_recorder.GetSourceForSourceId(dc_entry->source_id));
144 EXPECT_EQ(main_url,
145 test_ukm_recorder
146 .GetSourceForSourceId(*test_ukm_recorder.GetEntryMetric(
147 dc_entry, CreatedEntry::kNavigationSourceIdName))
148 ->url());
149 EXPECT_EQ(0, *test_ukm_recorder.GetEntryMetric(
150 dc_entry, CreatedEntry::kIsMainFrameName));
151 }
152
153 // Navigate top frame, try play.
154 NavigateFrameAndWait(web_contents()->GetMainFrame(), foo_url);
155 TryAutoplay(test_ukm_recorder, web_contents());
156
157 // Check that we recorded a UKM event using the main frame URL.
158 {
159 auto ukm_entries = test_ukm_recorder.GetEntriesByName(Entry::kEntryName);
160
161 ASSERT_EQ(4u, ukm_entries.size());
162 test_ukm_recorder.ExpectEntrySourceHasUrl(ukm_entries[3], foo_url);
163 }
164 }
165
166 } // namespace
167
168 } // namespace chrome
169