blob: f55fe38bb1e658c032331dc1530865cd651ea83d [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 ContentBrowserTest::SetUpCommandLine(command_line);
35 IsolateAllSitesForTesting(command_line);
36 }
37
38 void SetUpOnMainThread() override {
39 host_resolver()->AddRule("*", "127.0.0.1");
40 SetupCrossSiteRedirector(embedded_test_server());
41 ASSERT_TRUE(embedded_test_server()->Start());
42 }
43
ckitagawafbfbe0452020-04-24 19:13:4944 WebContents* web_contents() { return shell()->web_contents(); }
45
46 RenderFrameHostImpl* top_frame_host() {
Dave Tapuska327c06c92022-06-13 20:31:5147 return static_cast<RenderFrameHostImpl*>(
48 web_contents()->GetPrimaryMainFrame());
ckitagawafbfbe0452020-04-24 19:13:4949 }
50
ckitagawac2e43402020-01-17 00:09:2551 EmbeddingTokenBrowserTest(const EmbeddingTokenBrowserTest&) = delete;
52 EmbeddingTokenBrowserTest& operator=(const EmbeddingTokenBrowserTest&) =
53 delete;
54
55 private:
ckitagawa25042572020-05-28 14:43:1956 base::test::ScopedFeatureList scoped_feature_list_;
ckitagawac2e43402020-01-17 00:09:2557};
58
ckitagawa25042572020-05-28 14:43:1959IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest, EmbeddingTokenOnMainFrame) {
ckitagawac2e43402020-01-17 00:09:2560 GURL a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
61 GURL b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
62 // Starts without an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4963 EXPECT_FALSE(top_frame_host()->GetEmbeddingToken().has_value());
ckitagawac2e43402020-01-17 00:09:2564
ckitagawa25042572020-05-28 14:43:1965 // Embedding tokens should get added to the main frame.
ckitagawac2e43402020-01-17 00:09:2566 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
ckitagawa25042572020-05-28 14:43:1967 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
68 auto first_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:2569
70 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
ckitagawa25042572020-05-28 14:43:1971 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
72 EXPECT_NE(top_frame_host()->GetEmbeddingToken().value(), first_token);
ckitagawac2e43402020-01-17 00:09:2573}
74
75IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:1776 EmbeddingTokensAddedToCrossDocumentIFrames) {
ckitagawac2e43402020-01-17 00:09:2577 EXPECT_TRUE(NavigateToURL(
78 shell(), embedded_test_server()->GetURL(
79 "a.com", "/cross_site_iframe_factory.html?a(b(a),c,a)")));
ckitagawac2e43402020-01-17 00:09:2580
ckitagawafbfbe0452020-04-24 19:13:4981 ASSERT_EQ(3U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:1982 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
83 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:2584
85 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4986 auto child_0_token =
87 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:2588 ASSERT_TRUE(child_0_token.has_value());
89 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:1990 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:2591
92 // Child 0 (a) of Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:4993 ASSERT_EQ(1U, top_frame_host()->child_at(0)->child_count());
94 auto child_0_0_token = top_frame_host()
95 ->child_at(0)
96 ->child_at(0)
97 ->current_frame_host()
98 ->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:2599 ASSERT_TRUE(child_0_0_token.has_value());
100 EXPECT_NE(base::UnguessableToken::Null(), child_0_0_token);
ckitagawa25042572020-05-28 14:43:19101 EXPECT_NE(top_token, child_0_0_token);
ckitagawac2e43402020-01-17 00:09:25102 EXPECT_NE(child_0_token, child_0_0_token);
103
104 // Child 1 (c) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49105 auto child_1_token =
106 top_frame_host()->child_at(1)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:25107 ASSERT_TRUE(child_1_token.has_value());
108 EXPECT_NE(base::UnguessableToken::Null(), child_1_token);
ckitagawa25042572020-05-28 14:43:19109 EXPECT_NE(top_token, child_1_token);
ckitagawac2e43402020-01-17 00:09:25110 EXPECT_NE(child_0_token, child_1_token);
111 EXPECT_NE(child_0_0_token, child_1_token);
112
ckitagawa223004a2020-06-23 16:10:17113 // Child 2 (a) should have an embedding token.
114 auto child_2_token =
115 top_frame_host()->child_at(2)->current_frame_host()->GetEmbeddingToken();
116 ASSERT_TRUE(child_2_token.has_value());
117 EXPECT_NE(base::UnguessableToken::Null(), child_2_token);
118 EXPECT_NE(top_token, child_2_token);
119 EXPECT_NE(child_0_token, child_2_token);
120 EXPECT_NE(child_0_0_token, child_2_token);
ckitagawac2e43402020-01-17 00:09:25121
122 // TODO(ckitagawa): Somehow assert that the parent and child have matching
123 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
124}
125
126IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:17127 EmbeddingTokenSwapsOnCrossDocumentNavigation) {
ckitagawac2e43402020-01-17 00:09:25128 EXPECT_TRUE(NavigateToURL(
129 shell(), embedded_test_server()->GetURL(
130 "a.com", "/cross_site_iframe_factory.html?a(b)")));
ckitagawac2e43402020-01-17 00:09:25131
ckitagawafbfbe0452020-04-24 19:13:49132 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19133 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
134 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:25135
136 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49137 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawac2e43402020-01-17 00:09:25138 auto child_0_token = target->GetEmbeddingToken();
139 ASSERT_TRUE(child_0_token.has_value());
140 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:19141 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:25142
ckitagawa223004a2020-06-23 16:10:17143 // Navigate child 0 (b) to same-site the token should swap.
144 NavigateIframeToURL(shell()->web_contents(), "child-0",
145 embedded_test_server()
146 ->GetURL("b.com", "/site_isolation/")
147 .Resolve("blank.html"));
148 auto same_site_new_child_0_token =
149 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
150 ASSERT_TRUE(same_site_new_child_0_token.has_value());
151 EXPECT_NE(base::UnguessableToken::Null(), same_site_new_child_0_token);
152 EXPECT_NE(top_token, same_site_new_child_0_token);
153 EXPECT_NE(child_0_token, same_site_new_child_0_token);
154
ckitagawac2e43402020-01-17 00:09:25155 // Navigate child 0 (b) to another site (cross-process) the token should swap.
156 {
Rakina Zata Amni12a579b2023-08-08 05:57:54157 // The RenderFrameHost might have been replaced when the frame navigated.
158 target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawafbfbe0452020-04-24 19:13:49159 RenderFrameDeletedObserver deleted_observer(target);
ckitagawac2e43402020-01-17 00:09:25160 NavigateIframeToURL(shell()->web_contents(), "child-0",
161 embedded_test_server()
162 ->GetURL("c.com", "/site_isolation/")
163 .Resolve("blank.html"));
164 deleted_observer.WaitUntilDeleted();
165 }
ckitagawa223004a2020-06-23 16:10:17166 auto new_site_child_0_token =
ckitagawafbfbe0452020-04-24 19:13:49167 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17168 ASSERT_TRUE(same_site_new_child_0_token.has_value());
169 EXPECT_NE(base::UnguessableToken::Null(), new_site_child_0_token);
170 EXPECT_NE(top_token, new_site_child_0_token);
171 EXPECT_NE(child_0_token, new_site_child_0_token);
172 EXPECT_NE(same_site_new_child_0_token, new_site_child_0_token);
ckitagawac2e43402020-01-17 00:09:25173
174 // TODO(ckitagawa): Somehow assert that the parent and child have matching
175 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
176}
177
ckitagawa223004a2020-06-23 16:10:17178IN_PROC_BROWSER_TEST_F(
179 EmbeddingTokenBrowserTest,
180 EmbeddingTokenNotChangedOnSubframeSameDocumentNavigation) {
ckitagawac2e43402020-01-17 00:09:25181 EXPECT_TRUE(NavigateToURL(
182 shell(), embedded_test_server()->GetURL(
183 "a.com", "/cross_site_iframe_factory.html?a(a)")));
ckitagawac2e43402020-01-17 00:09:25184
ckitagawafbfbe0452020-04-24 19:13:49185 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19186 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
187 auto top_token = top_frame_host()->GetEmbeddingToken().value();
188
ckitagawa223004a2020-06-23 16:10:17189 // Child 0 (a) should have an embedding token.
190 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
191 auto child_0_token = target->GetEmbeddingToken();
192 ASSERT_TRUE(child_0_token.has_value());
193 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
194 EXPECT_NE(top_token, child_0_token);
195
ckitagawac2e43402020-01-17 00:09:25196 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
197 // Navigate child 0 to another site (cross-process) a token should be created.
198 {
199 RenderFrameDeletedObserver deleted_observer(
ckitagawafbfbe0452020-04-24 19:13:49200 top_frame_host()->child_at(0)->current_frame_host());
201 NavigateIframeToURL(web_contents(), "child-0", b_url.Resolve("blank.html"));
ckitagawac2e43402020-01-17 00:09:25202 deleted_observer.WaitUntilDeleted();
203 }
204
ckitagawa223004a2020-06-23 16:10:17205 // Child 0 (b) should have a new embedding token.
ckitagawafbfbe0452020-04-24 19:13:49206 auto new_child_0_token =
207 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17208 ASSERT_TRUE(child_0_token.has_value());
209 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19210 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17211 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawa25042572020-05-28 14:43:19212
ckitagawa223004a2020-06-23 16:10:17213 // Navigate child 0 (b) to same document the token should not swap.
214 NavigateIframeToURL(web_contents(), "child-0",
215 b_url.Resolve("blank.html#foo"));
216 auto same_document_new_child_0_token =
217 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
218 ASSERT_TRUE(same_document_new_child_0_token.has_value());
219 EXPECT_EQ(new_child_0_token, same_document_new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25220
221 // TODO(ckitagawa): Somehow assert that the parent and child have matching
222 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
223}
224
225IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:17226 EmbeddingTokenChangedOnSubframeNavigationToNewDocument) {
ckitagawac2e43402020-01-17 00:09:25227 auto a_url = embedded_test_server()->GetURL("a.com", "/");
228 EXPECT_TRUE(NavigateToURL(
229 shell(), a_url.Resolve("cross_site_iframe_factory.html?a(b)")));
ckitagawac2e43402020-01-17 00:09:25230
ckitagawafbfbe0452020-04-24 19:13:49231 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19232 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
233 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:25234
235 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49236 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawac2e43402020-01-17 00:09:25237 auto child_0_token = target->GetEmbeddingToken();
238 ASSERT_TRUE(child_0_token.has_value());
239 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:19240 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:25241
ckitagawa223004a2020-06-23 16:10:17242 // Navigate child 0 (b) to the same site as the main frame. This should create
243 // an embedding token.
ckitagawac2e43402020-01-17 00:09:25244 {
ckitagawafbfbe0452020-04-24 19:13:49245 RenderFrameDeletedObserver deleted_observer(target);
246 NavigateIframeToURL(web_contents(), "child-0",
ckitagawac2e43402020-01-17 00:09:25247 a_url.Resolve("site_isolation/").Resolve("blank.html"));
248 deleted_observer.WaitUntilDeleted();
249 }
ckitagawac2e43402020-01-17 00:09:25250
ckitagawafbfbe0452020-04-24 19:13:49251 auto new_child_0_token =
252 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:25253 ASSERT_TRUE(new_child_0_token.has_value());
254 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19255 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17256 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25257
258 // TODO(ckitagawa): Somehow assert that the parent and child have matching
259 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
260}
261
ckitagawa25042572020-05-28 14:43:19262IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
263 BackForwardCacheCrossDocument) {
264 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
265 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
266 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
267
268 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
269 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
270
271 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
272 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
273 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
274 EXPECT_NE(top_token_a, top_token_b);
275
276 // Navigate back to the first origin. The back forward cache should keep
277 // the embedding token.
278 web_contents()->GetController().GoBack();
279 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
280
281 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
282 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
283 EXPECT_EQ(top_token_a, top_token_a_prime);
284}
285
286IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
287 BackForwardCacheCrossDocumentAfterSameDocument) {
288 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
289 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
290 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
291
292 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
293 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
294
295 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
296 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
297 EXPECT_EQ(top_frame_host()->GetEmbeddingToken().value(), top_token_a);
298
299 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
300 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
301 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
302 EXPECT_NE(top_token_a, top_token_b);
303
304 // Navigate back to the first origin. The back forward cache should keep
305 // the embedding token even when the embedding token is not present in the
306 // most recent navigation.
307 web_contents()->GetController().GoBack();
308 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
309
310 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
311 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
312 EXPECT_EQ(top_token_a, top_token_a_prime);
313}
314
315IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
316 SameDocumentHistoryPreservesTokens) {
317 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
318 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
319
320 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
321 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
322
323 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
324 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
325 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
326 EXPECT_EQ(top_token_a, top_token_a_prime);
327
328 // Navigate back to before the fragment was added. This should preserve the
329 // embedding token.
330 web_contents()->GetController().GoBack();
331 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
332
333 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
334 auto top_token_a_prime_prime = top_frame_host()->GetEmbeddingToken().value();
335 EXPECT_EQ(top_token_a, top_token_a_prime_prime);
336}
337
ckitagawac2e43402020-01-17 00:09:25338} // namespace content