blob: 2a67df36c707633b1031ac790a0d92c5f39a06b6 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2019 The Chromium Authors
ckitagawac2e43402020-01-17 00:09:252// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
ckitagawa25042572020-05-28 14:43:195#include "base/test/scoped_feature_list.h"
ckitagawac2e43402020-01-17 00:09:256#include "base/unguessable_token.h"
danakjc492bf82020-09-09 20:02:447#include "content/browser/renderer_host/frame_tree.h"
ckitagawac2e43402020-01-17 00:09:258#include "content/browser/web_contents/web_contents_impl.h"
Fergal Daly690207f62020-04-07 15:33:569#include "content/common/content_navigation_policy.h"
Ming-Ying Chung72636182023-02-28 12:16:0410#include "content/public/test/back_forward_cache_util.h"
Peter Kasting919ce652020-05-07 10:22:3611#include "content/public/test/browser_test.h"
ckitagawac2e43402020-01-17 00:09:2512#include "content/public/test/browser_test_utils.h"
13#include "content/public/test/content_browser_test.h"
14#include "content/public/test/content_browser_test_utils.h"
15#include "content/public/test/test_utils.h"
16#include "content/shell/browser/shell.h"
17#include "content/test/content_browser_test_utils_internal.h"
18#include "net/dns/mock_host_resolver.h"
19#include "net/test/embedded_test_server/embedded_test_server.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace content {
23
24class EmbeddingTokenBrowserTest : public ContentBrowserTest {
25 public:
26 EmbeddingTokenBrowserTest() = default;
27
28 void SetUpCommandLine(base::CommandLine* command_line) override {
Sreeja Kamishetty92006e02021-02-05 05:18:1129 scoped_feature_list_.InitWithFeaturesAndParameters(
Ming-Ying Chung72636182023-02-28 12:16:0430 GetDefaultEnabledBackForwardCacheFeaturesForTesting(
31 /*ignore_outstanding_network_request=*/false),
32 GetDefaultDisabledBackForwardCacheFeaturesForTesting());
Sreeja Kamishetty92006e02021-02-05 05:18:1133
ckitagawac2e43402020-01-17 00:09:2534 IsolateAllSitesForTesting(command_line);
35 }
36
37 void SetUpOnMainThread() override {
38 host_resolver()->AddRule("*", "127.0.0.1");
39 SetupCrossSiteRedirector(embedded_test_server());
40 ASSERT_TRUE(embedded_test_server()->Start());
41 }
42
ckitagawafbfbe0452020-04-24 19:13:4943 WebContents* web_contents() { return shell()->web_contents(); }
44
45 RenderFrameHostImpl* top_frame_host() {
Dave Tapuska327c06c92022-06-13 20:31:5146 return static_cast<RenderFrameHostImpl*>(
47 web_contents()->GetPrimaryMainFrame());
ckitagawafbfbe0452020-04-24 19:13:4948 }
49
ckitagawac2e43402020-01-17 00:09:2550 EmbeddingTokenBrowserTest(const EmbeddingTokenBrowserTest&) = delete;
51 EmbeddingTokenBrowserTest& operator=(const EmbeddingTokenBrowserTest&) =
52 delete;
53
54 private:
ckitagawa25042572020-05-28 14:43:1955 base::test::ScopedFeatureList scoped_feature_list_;
ckitagawac2e43402020-01-17 00:09:2556};
57
ckitagawa25042572020-05-28 14:43:1958IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest, EmbeddingTokenOnMainFrame) {
ckitagawac2e43402020-01-17 00:09:2559 GURL a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
60 GURL b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
61 // Starts without an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4962 EXPECT_FALSE(top_frame_host()->GetEmbeddingToken().has_value());
ckitagawac2e43402020-01-17 00:09:2563
ckitagawa25042572020-05-28 14:43:1964 // Embedding tokens should get added to the main frame.
ckitagawac2e43402020-01-17 00:09:2565 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
ckitagawa25042572020-05-28 14:43:1966 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
67 auto first_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:2568
69 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
ckitagawa25042572020-05-28 14:43:1970 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
71 EXPECT_NE(top_frame_host()->GetEmbeddingToken().value(), first_token);
ckitagawac2e43402020-01-17 00:09:2572}
73
74IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:1775 EmbeddingTokensAddedToCrossDocumentIFrames) {
ckitagawac2e43402020-01-17 00:09:2576 EXPECT_TRUE(NavigateToURL(
77 shell(), embedded_test_server()->GetURL(
78 "a.com", "/cross_site_iframe_factory.html?a(b(a),c,a)")));
ckitagawac2e43402020-01-17 00:09:2579
ckitagawafbfbe0452020-04-24 19:13:4980 ASSERT_EQ(3U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:1981 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
82 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:2583
84 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4985 auto child_0_token =
86 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:2587 ASSERT_TRUE(child_0_token.has_value());
88 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:1989 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:2590
91 // Child 0 (a) of Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4992 ASSERT_EQ(1U, top_frame_host()->child_at(0)->child_count());
93 auto child_0_0_token = top_frame_host()
94 ->child_at(0)
95 ->child_at(0)
96 ->current_frame_host()
97 ->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:2598 ASSERT_TRUE(child_0_0_token.has_value());
99 EXPECT_NE(base::UnguessableToken::Null(), child_0_0_token);
ckitagawa25042572020-05-28 14:43:19100 EXPECT_NE(top_token, child_0_0_token);
ckitagawac2e43402020-01-17 00:09:25101 EXPECT_NE(child_0_token, child_0_0_token);
102
103 // Child 1 (c) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49104 auto child_1_token =
105 top_frame_host()->child_at(1)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:25106 ASSERT_TRUE(child_1_token.has_value());
107 EXPECT_NE(base::UnguessableToken::Null(), child_1_token);
ckitagawa25042572020-05-28 14:43:19108 EXPECT_NE(top_token, child_1_token);
ckitagawac2e43402020-01-17 00:09:25109 EXPECT_NE(child_0_token, child_1_token);
110 EXPECT_NE(child_0_0_token, child_1_token);
111
ckitagawa223004a2020-06-23 16:10:17112 // Child 2 (a) should have an embedding token.
113 auto child_2_token =
114 top_frame_host()->child_at(2)->current_frame_host()->GetEmbeddingToken();
115 ASSERT_TRUE(child_2_token.has_value());
116 EXPECT_NE(base::UnguessableToken::Null(), child_2_token);
117 EXPECT_NE(top_token, child_2_token);
118 EXPECT_NE(child_0_token, child_2_token);
119 EXPECT_NE(child_0_0_token, child_2_token);
ckitagawac2e43402020-01-17 00:09:25120
121 // TODO(ckitagawa): Somehow assert that the parent and child have matching
122 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
123}
124
125IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:17126 EmbeddingTokenSwapsOnCrossDocumentNavigation) {
ckitagawac2e43402020-01-17 00:09:25127 EXPECT_TRUE(NavigateToURL(
128 shell(), embedded_test_server()->GetURL(
129 "a.com", "/cross_site_iframe_factory.html?a(b)")));
ckitagawac2e43402020-01-17 00:09:25130
ckitagawafbfbe0452020-04-24 19:13:49131 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19132 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
133 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:25134
135 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49136 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawac2e43402020-01-17 00:09:25137 auto child_0_token = target->GetEmbeddingToken();
138 ASSERT_TRUE(child_0_token.has_value());
139 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:19140 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:25141
ckitagawa223004a2020-06-23 16:10:17142 // Navigate child 0 (b) to same-site the token should swap.
143 NavigateIframeToURL(shell()->web_contents(), "child-0",
144 embedded_test_server()
145 ->GetURL("b.com", "/site_isolation/")
146 .Resolve("blank.html"));
147 auto same_site_new_child_0_token =
148 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
149 ASSERT_TRUE(same_site_new_child_0_token.has_value());
150 EXPECT_NE(base::UnguessableToken::Null(), same_site_new_child_0_token);
151 EXPECT_NE(top_token, same_site_new_child_0_token);
152 EXPECT_NE(child_0_token, same_site_new_child_0_token);
153
ckitagawac2e43402020-01-17 00:09:25154 // Navigate child 0 (b) to another site (cross-process) the token should swap.
155 {
Rakina Zata Amni12a579b2023-08-08 05:57:54156 // The RenderFrameHost might have been replaced when the frame navigated.
157 target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawafbfbe0452020-04-24 19:13:49158 RenderFrameDeletedObserver deleted_observer(target);
ckitagawac2e43402020-01-17 00:09:25159 NavigateIframeToURL(shell()->web_contents(), "child-0",
160 embedded_test_server()
161 ->GetURL("c.com", "/site_isolation/")
162 .Resolve("blank.html"));
163 deleted_observer.WaitUntilDeleted();
164 }
ckitagawa223004a2020-06-23 16:10:17165 auto new_site_child_0_token =
ckitagawafbfbe0452020-04-24 19:13:49166 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17167 ASSERT_TRUE(same_site_new_child_0_token.has_value());
168 EXPECT_NE(base::UnguessableToken::Null(), new_site_child_0_token);
169 EXPECT_NE(top_token, new_site_child_0_token);
170 EXPECT_NE(child_0_token, new_site_child_0_token);
171 EXPECT_NE(same_site_new_child_0_token, new_site_child_0_token);
ckitagawac2e43402020-01-17 00:09:25172
173 // TODO(ckitagawa): Somehow assert that the parent and child have matching
174 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
175}
176
ckitagawa223004a2020-06-23 16:10:17177IN_PROC_BROWSER_TEST_F(
178 EmbeddingTokenBrowserTest,
179 EmbeddingTokenNotChangedOnSubframeSameDocumentNavigation) {
ckitagawac2e43402020-01-17 00:09:25180 EXPECT_TRUE(NavigateToURL(
181 shell(), embedded_test_server()->GetURL(
182 "a.com", "/cross_site_iframe_factory.html?a(a)")));
ckitagawac2e43402020-01-17 00:09:25183
ckitagawafbfbe0452020-04-24 19:13:49184 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19185 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
186 auto top_token = top_frame_host()->GetEmbeddingToken().value();
187
ckitagawa223004a2020-06-23 16:10:17188 // Child 0 (a) should have an embedding token.
189 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
190 auto child_0_token = target->GetEmbeddingToken();
191 ASSERT_TRUE(child_0_token.has_value());
192 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
193 EXPECT_NE(top_token, child_0_token);
194
ckitagawac2e43402020-01-17 00:09:25195 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
196 // Navigate child 0 to another site (cross-process) a token should be created.
197 {
198 RenderFrameDeletedObserver deleted_observer(
ckitagawafbfbe0452020-04-24 19:13:49199 top_frame_host()->child_at(0)->current_frame_host());
200 NavigateIframeToURL(web_contents(), "child-0", b_url.Resolve("blank.html"));
ckitagawac2e43402020-01-17 00:09:25201 deleted_observer.WaitUntilDeleted();
202 }
203
ckitagawa223004a2020-06-23 16:10:17204 // Child 0 (b) should have a new embedding token.
ckitagawafbfbe0452020-04-24 19:13:49205 auto new_child_0_token =
206 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17207 ASSERT_TRUE(child_0_token.has_value());
208 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19209 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17210 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawa25042572020-05-28 14:43:19211
ckitagawa223004a2020-06-23 16:10:17212 // Navigate child 0 (b) to same document the token should not swap.
213 NavigateIframeToURL(web_contents(), "child-0",
214 b_url.Resolve("blank.html#foo"));
215 auto same_document_new_child_0_token =
216 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
217 ASSERT_TRUE(same_document_new_child_0_token.has_value());
218 EXPECT_EQ(new_child_0_token, same_document_new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25219
220 // TODO(ckitagawa): Somehow assert that the parent and child have matching
221 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
222}
223
224IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:17225 EmbeddingTokenChangedOnSubframeNavigationToNewDocument) {
ckitagawac2e43402020-01-17 00:09:25226 auto a_url = embedded_test_server()->GetURL("a.com", "/");
227 EXPECT_TRUE(NavigateToURL(
228 shell(), a_url.Resolve("cross_site_iframe_factory.html?a(b)")));
ckitagawac2e43402020-01-17 00:09:25229
ckitagawafbfbe0452020-04-24 19:13:49230 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19231 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
232 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:25233
234 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49235 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawac2e43402020-01-17 00:09:25236 auto child_0_token = target->GetEmbeddingToken();
237 ASSERT_TRUE(child_0_token.has_value());
238 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:19239 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:25240
ckitagawa223004a2020-06-23 16:10:17241 // Navigate child 0 (b) to the same site as the main frame. This should create
242 // an embedding token.
ckitagawac2e43402020-01-17 00:09:25243 {
ckitagawafbfbe0452020-04-24 19:13:49244 RenderFrameDeletedObserver deleted_observer(target);
245 NavigateIframeToURL(web_contents(), "child-0",
ckitagawac2e43402020-01-17 00:09:25246 a_url.Resolve("site_isolation/").Resolve("blank.html"));
247 deleted_observer.WaitUntilDeleted();
248 }
ckitagawac2e43402020-01-17 00:09:25249
ckitagawafbfbe0452020-04-24 19:13:49250 auto new_child_0_token =
251 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:25252 ASSERT_TRUE(new_child_0_token.has_value());
253 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19254 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17255 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25256
257 // TODO(ckitagawa): Somehow assert that the parent and child have matching
258 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
259}
260
ckitagawa25042572020-05-28 14:43:19261IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
262 BackForwardCacheCrossDocument) {
263 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
264 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
265 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
266
267 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
268 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
269
270 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
271 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
272 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
273 EXPECT_NE(top_token_a, top_token_b);
274
275 // Navigate back to the first origin. The back forward cache should keep
276 // the embedding token.
277 web_contents()->GetController().GoBack();
278 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
279
280 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
281 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
282 EXPECT_EQ(top_token_a, top_token_a_prime);
283}
284
285IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
286 BackForwardCacheCrossDocumentAfterSameDocument) {
287 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
288 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
289 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
290
291 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
292 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
293
294 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
295 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
296 EXPECT_EQ(top_frame_host()->GetEmbeddingToken().value(), top_token_a);
297
298 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
299 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
300 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
301 EXPECT_NE(top_token_a, top_token_b);
302
303 // Navigate back to the first origin. The back forward cache should keep
304 // the embedding token even when the embedding token is not present in the
305 // most recent navigation.
306 web_contents()->GetController().GoBack();
307 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
308
309 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
310 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
311 EXPECT_EQ(top_token_a, top_token_a_prime);
312}
313
314IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
315 SameDocumentHistoryPreservesTokens) {
316 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
317 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
318
319 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
320 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
321
322 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
323 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
324 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
325 EXPECT_EQ(top_token_a, top_token_a_prime);
326
327 // Navigate back to before the fragment was added. This should preserve the
328 // embedding token.
329 web_contents()->GetController().GoBack();
330 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
331
332 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
333 auto top_token_a_prime_prime = top_frame_host()->GetEmbeddingToken().value();
334 EXPECT_EQ(top_token_a, top_token_a_prime_prime);
335}
336
ckitagawac2e43402020-01-17 00:09:25337} // namespace content