blob: 697804553120158513b52fd5b285ff649221c6bb [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 {
Fergal Dalybac2a2f2020-10-27 23:37:02157 if (ShouldCreateNewHostForSameSiteSubframe()) {
158 // The RenderFrameHost was been replaced when the frame navigated.
159 target = top_frame_host()->child_at(0)->current_frame_host();
160 }
ckitagawafbfbe0452020-04-24 19:13:49161 RenderFrameDeletedObserver deleted_observer(target);
ckitagawac2e43402020-01-17 00:09:25162 NavigateIframeToURL(shell()->web_contents(), "child-0",
163 embedded_test_server()
164 ->GetURL("c.com", "/site_isolation/")
165 .Resolve("blank.html"));
166 deleted_observer.WaitUntilDeleted();
167 }
ckitagawa223004a2020-06-23 16:10:17168 auto new_site_child_0_token =
ckitagawafbfbe0452020-04-24 19:13:49169 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17170 ASSERT_TRUE(same_site_new_child_0_token.has_value());
171 EXPECT_NE(base::UnguessableToken::Null(), new_site_child_0_token);
172 EXPECT_NE(top_token, new_site_child_0_token);
173 EXPECT_NE(child_0_token, new_site_child_0_token);
174 EXPECT_NE(same_site_new_child_0_token, new_site_child_0_token);
ckitagawac2e43402020-01-17 00:09:25175
176 // TODO(ckitagawa): Somehow assert that the parent and child have matching
177 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
178}
179
ckitagawa223004a2020-06-23 16:10:17180IN_PROC_BROWSER_TEST_F(
181 EmbeddingTokenBrowserTest,
182 EmbeddingTokenNotChangedOnSubframeSameDocumentNavigation) {
ckitagawac2e43402020-01-17 00:09:25183 EXPECT_TRUE(NavigateToURL(
184 shell(), embedded_test_server()->GetURL(
185 "a.com", "/cross_site_iframe_factory.html?a(a)")));
ckitagawac2e43402020-01-17 00:09:25186
ckitagawafbfbe0452020-04-24 19:13:49187 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19188 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
189 auto top_token = top_frame_host()->GetEmbeddingToken().value();
190
ckitagawa223004a2020-06-23 16:10:17191 // Child 0 (a) should have an embedding token.
192 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
193 auto child_0_token = target->GetEmbeddingToken();
194 ASSERT_TRUE(child_0_token.has_value());
195 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
196 EXPECT_NE(top_token, child_0_token);
197
ckitagawac2e43402020-01-17 00:09:25198 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
199 // Navigate child 0 to another site (cross-process) a token should be created.
200 {
201 RenderFrameDeletedObserver deleted_observer(
ckitagawafbfbe0452020-04-24 19:13:49202 top_frame_host()->child_at(0)->current_frame_host());
203 NavigateIframeToURL(web_contents(), "child-0", b_url.Resolve("blank.html"));
ckitagawac2e43402020-01-17 00:09:25204 deleted_observer.WaitUntilDeleted();
205 }
206
ckitagawa223004a2020-06-23 16:10:17207 // Child 0 (b) should have a new embedding token.
ckitagawafbfbe0452020-04-24 19:13:49208 auto new_child_0_token =
209 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawa223004a2020-06-23 16:10:17210 ASSERT_TRUE(child_0_token.has_value());
211 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19212 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17213 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawa25042572020-05-28 14:43:19214
ckitagawa223004a2020-06-23 16:10:17215 // Navigate child 0 (b) to same document the token should not swap.
216 NavigateIframeToURL(web_contents(), "child-0",
217 b_url.Resolve("blank.html#foo"));
218 auto same_document_new_child_0_token =
219 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
220 ASSERT_TRUE(same_document_new_child_0_token.has_value());
221 EXPECT_EQ(new_child_0_token, same_document_new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25222
223 // TODO(ckitagawa): Somehow assert that the parent and child have matching
224 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
225}
226
227IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
ckitagawa223004a2020-06-23 16:10:17228 EmbeddingTokenChangedOnSubframeNavigationToNewDocument) {
ckitagawac2e43402020-01-17 00:09:25229 auto a_url = embedded_test_server()->GetURL("a.com", "/");
230 EXPECT_TRUE(NavigateToURL(
231 shell(), a_url.Resolve("cross_site_iframe_factory.html?a(b)")));
ckitagawac2e43402020-01-17 00:09:25232
ckitagawafbfbe0452020-04-24 19:13:49233 ASSERT_EQ(1U, top_frame_host()->child_count());
ckitagawa25042572020-05-28 14:43:19234 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
235 auto top_token = top_frame_host()->GetEmbeddingToken().value();
ckitagawac2e43402020-01-17 00:09:25236
237 // Child 0 (b) should have an embedding token.
ckitagawafbfbe0452020-04-24 19:13:49238 RenderFrameHost* target = top_frame_host()->child_at(0)->current_frame_host();
ckitagawac2e43402020-01-17 00:09:25239 auto child_0_token = target->GetEmbeddingToken();
240 ASSERT_TRUE(child_0_token.has_value());
241 EXPECT_NE(base::UnguessableToken::Null(), child_0_token);
ckitagawa25042572020-05-28 14:43:19242 EXPECT_NE(top_token, child_0_token);
ckitagawac2e43402020-01-17 00:09:25243
ckitagawa223004a2020-06-23 16:10:17244 // Navigate child 0 (b) to the same site as the main frame. This should create
245 // an embedding token.
ckitagawac2e43402020-01-17 00:09:25246 {
ckitagawafbfbe0452020-04-24 19:13:49247 RenderFrameDeletedObserver deleted_observer(target);
248 NavigateIframeToURL(web_contents(), "child-0",
ckitagawac2e43402020-01-17 00:09:25249 a_url.Resolve("site_isolation/").Resolve("blank.html"));
250 deleted_observer.WaitUntilDeleted();
251 }
ckitagawac2e43402020-01-17 00:09:25252
ckitagawafbfbe0452020-04-24 19:13:49253 auto new_child_0_token =
254 top_frame_host()->child_at(0)->current_frame_host()->GetEmbeddingToken();
ckitagawac2e43402020-01-17 00:09:25255 ASSERT_TRUE(new_child_0_token.has_value());
256 EXPECT_NE(base::UnguessableToken::Null(), new_child_0_token);
ckitagawa25042572020-05-28 14:43:19257 EXPECT_NE(top_token, new_child_0_token);
ckitagawa223004a2020-06-23 16:10:17258 EXPECT_NE(child_0_token, new_child_0_token);
ckitagawac2e43402020-01-17 00:09:25259
260 // TODO(ckitagawa): Somehow assert that the parent and child have matching
261 // embedding tokens in parent HTMLOwnerElement and child LocalFrame.
262}
263
ckitagawa25042572020-05-28 14:43:19264IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
265 BackForwardCacheCrossDocument) {
266 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
267 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
268 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
269
270 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
271 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
272
273 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
274 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
275 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
276 EXPECT_NE(top_token_a, top_token_b);
277
278 // Navigate back to the first origin. The back forward cache should keep
279 // the embedding token.
280 web_contents()->GetController().GoBack();
281 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
282
283 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
284 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
285 EXPECT_EQ(top_token_a, top_token_a_prime);
286}
287
288IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
289 BackForwardCacheCrossDocumentAfterSameDocument) {
290 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
291 auto b_url = embedded_test_server()->GetURL("b.com", "/site_isolation/");
292 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
293
294 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
295 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
296
297 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
298 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
299 EXPECT_EQ(top_frame_host()->GetEmbeddingToken().value(), top_token_a);
300
301 EXPECT_TRUE(NavigateToURL(shell(), b_url.Resolve("blank.html")));
302 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
303 auto top_token_b = top_frame_host()->GetEmbeddingToken().value();
304 EXPECT_NE(top_token_a, top_token_b);
305
306 // Navigate back to the first origin. The back forward cache should keep
307 // the embedding token even when the embedding token is not present in the
308 // most recent navigation.
309 web_contents()->GetController().GoBack();
310 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
311
312 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
313 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
314 EXPECT_EQ(top_token_a, top_token_a_prime);
315}
316
317IN_PROC_BROWSER_TEST_F(EmbeddingTokenBrowserTest,
318 SameDocumentHistoryPreservesTokens) {
319 auto a_url = embedded_test_server()->GetURL("a.com", "/site_isolation/");
320 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html")));
321
322 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
323 auto top_token_a = top_frame_host()->GetEmbeddingToken().value();
324
325 EXPECT_TRUE(NavigateToURL(shell(), a_url.Resolve("blank.html#foo")));
326 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
327 auto top_token_a_prime = top_frame_host()->GetEmbeddingToken().value();
328 EXPECT_EQ(top_token_a, top_token_a_prime);
329
330 // Navigate back to before the fragment was added. This should preserve the
331 // embedding token.
332 web_contents()->GetController().GoBack();
333 EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
334
335 EXPECT_TRUE(top_frame_host()->GetEmbeddingToken().has_value());
336 auto top_token_a_prime_prime = top_frame_host()->GetEmbeddingToken().value();
337 EXPECT_EQ(top_token_a, top_token_a_prime_prime);
338}
339
ckitagawac2e43402020-01-17 00:09:25340} // namespace content