Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: content/browser/frame_host/navigation_controller_impl_browsertest.cc

Issue 2454233002: Fix history nav to a script-injected about:blank frame. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/browser/frame_host/navigation_entry_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/frame_host/navigation_controller_impl.h" 5 #include "content/browser/frame_host/navigation_controller_impl.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 3166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); 3177 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
3178 3178
3179 // 3. Go back, recreating the iframe. 3179 // 3. Go back, recreating the iframe.
3180 { 3180 {
3181 TestNavigationObserver back_load_observer(shell()->web_contents()); 3181 TestNavigationObserver back_load_observer(shell()->web_contents());
3182 controller.GoBack(); 3182 controller.GoBack();
3183 back_load_observer.Wait(); 3183 back_load_observer.Wait();
3184 } 3184 }
3185 ASSERT_EQ(1U, root->child_count()); 3185 ASSERT_EQ(1U, root->child_count());
3186 EXPECT_EQ(main_url, root->current_url()); 3186 EXPECT_EQ(main_url, root->current_url());
3187 3187 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3188 // TODO(creis): The child's current_url should be about:blank, but we're not
3189 // currently getting a commit in this case. For now, we'll lack a commit for
3190 // this frame, similar to the slow URL case. See https://crbug.com/626416.
3191 if (SiteIsolationPolicy::UseSubframeNavigationEntries())
3192 EXPECT_TRUE(root->child_at(0)->current_url().is_empty());
3193 else
3194 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3195 3188
3196 // Verify that the parent was able to script the iframe. 3189 // Verify that the parent was able to script the iframe.
3197 { 3190 {
3198 std::string value; 3191 std::string value;
3199 EXPECT_TRUE(ExecuteScriptAndExtractString( 3192 EXPECT_TRUE(ExecuteScriptAndExtractString(
3200 root->child_at(0), 3193 root->child_at(0),
3201 "domAutomationController.send(document.body.innerHTML)", &value)); 3194 "domAutomationController.send(document.body.innerHTML)", &value));
3202 EXPECT_EQ(expected_text, value); 3195 EXPECT_EQ(expected_text, value);
3203 } 3196 }
3204 3197
3205 EXPECT_EQ(2, controller.GetEntryCount()); 3198 EXPECT_EQ(2, controller.GetEntryCount());
3206 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); 3199 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
3207 EXPECT_EQ(entry, controller.GetLastCommittedEntry()); 3200 EXPECT_EQ(entry, controller.GetLastCommittedEntry());
3208 3201
3209 // The entry should have a FrameNavigationEntry for the blank subframe. 3202 // The entry should have a FrameNavigationEntry for the blank subframe.
3210 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) { 3203 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3211 ASSERT_EQ(1U, entry->root_node()->children.size()); 3204 ASSERT_EQ(1U, entry->root_node()->children.size());
3212 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url()); 3205 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3213 } 3206 }
3214 } 3207 }
3215 3208
3209 // Verify that we correctly load nested iframes injected into a page if we go
3210 // back and recreate them. Also confirm that form values are not restored for
3211 // forms injected into about:blank pages. See https://crbug.com/657896.
3212 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
3213 FrameNavigationEntry_RecreatedInjectedBlankSubframe) {
3214 // 1. Start on a page that injects a nested iframe into an injected
3215 // about:blank iframe.
3216 GURL main_url(embedded_test_server()->GetURL(
3217 "/navigation_controller/inject_subframe_into_blank_iframe.html"));
3218 GURL blank_url(url::kAboutBlankURL);
3219 GURL inner_url(
3220 embedded_test_server()->GetURL("/navigation_controller/form.html"));
3221 EXPECT_TRUE(NavigateToURL(shell(), main_url));
3222 NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
3223 shell()->web_contents()->GetController());
3224 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
3225 ->GetFrameTree()
3226 ->root();
3227
3228 // Verify that the inner iframe was able to load.
3229 ASSERT_EQ(1U, root->child_count());
3230 ASSERT_EQ(1U, root->child_at(0)->child_count());
3231 ASSERT_EQ(0U, root->child_at(0)->child_at(0)->child_count());
3232 EXPECT_EQ(main_url, root->current_url());
3233 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3234 EXPECT_EQ(inner_url, root->child_at(0)->child_at(0)->current_url());
3235
3236 EXPECT_EQ(1, controller.GetEntryCount());
3237 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
3238 NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
3239
3240 // The entry should have FrameNavigationEntries for the subframes.
3241 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3242 ASSERT_EQ(1U, entry->root_node()->children.size());
3243 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3244 EXPECT_EQ(inner_url,
3245 entry->root_node()->children[0]->children[0]->frame_entry->url());
3246 }
3247
3248 // Set a value in the form which will be stored in the PageState.
3249 EXPECT_TRUE(
3250 ExecuteScript(root->child_at(0)->child_at(0),
3251 "document.getElementById('itext').value = 'modified';"));
3252
3253 // 2. Navigate the main frame same-site, destroying the subframes.
3254 GURL main_url_2(embedded_test_server()->GetURL(
3255 "/navigation_controller/simple_page_1.html"));
3256 EXPECT_TRUE(NavigateToURL(shell(), main_url_2));
3257 ASSERT_EQ(0U, root->child_count());
3258 EXPECT_EQ(main_url_2, root->current_url());
3259
3260 EXPECT_EQ(2, controller.GetEntryCount());
3261 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
3262
3263 // 3. Go back, recreating the subframes.
3264 {
3265 TestNavigationObserver back_load_observer(shell()->web_contents());
3266 controller.GoBack();
3267 back_load_observer.Wait();
3268 }
3269 ASSERT_EQ(1U, root->child_count());
3270 EXPECT_EQ(main_url, root->current_url());
3271 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3272
3273 // Verify that the inner iframe went to the correct URL.
3274 EXPECT_EQ(inner_url, root->child_at(0)->child_at(0)->current_url());
3275
3276 EXPECT_EQ(2, controller.GetEntryCount());
3277 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
3278 EXPECT_EQ(entry, controller.GetLastCommittedEntry());
3279
3280 // The entry should have FrameNavigationEntries for the subframes.
3281 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3282 ASSERT_EQ(1U, entry->root_node()->children.size());
3283 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3284 EXPECT_EQ(inner_url,
3285 entry->root_node()->children[0]->children[0]->frame_entry->url());
3286 }
3287
3288 // With injected about:blank iframes, we never restore form values from
3289 // PageState.
3290 std::string form_value = "fail";
3291 EXPECT_TRUE(
3292 ExecuteScriptAndExtractString(root->child_at(0)->child_at(0),
3293 "window.domAutomationController.send("
3294 "document.getElementById('itext').value);",
3295 &form_value));
3296 EXPECT_EQ("", form_value);
3297 }
3298
3299 // Verify that we correctly load a nested iframe created by an injected iframe
3300 // srcdoc if we go back and recreate the frames. Also verify that form values
3301 // are correctly restored for forms within srcdoc frames, unlike forms injected
3302 // into about:blank pages (as tested in
3303 // FrameNavigationEntry_RecreatedInjectedBlankSubframe).
3304 //
3305 // This test worked before and after the fix for https://crbug.com/657896, but
3306 // it failed with a preliminary version of the fix.
3307 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
3308 FrameNavigationEntry_RecreatedInjectedSrcdocSubframe) {
3309 // 1. Start on a page that injects a nested iframe srcdoc which contains a
3310 // nested iframe.
3311 GURL main_url(embedded_test_server()->GetURL(
3312 "/navigation_controller/inject_iframe_srcdoc_with_nested_frame.html"));
3313 GURL blank_url(url::kAboutBlankURL);
3314 GURL inner_url(
3315 embedded_test_server()->GetURL("/navigation_controller/form.html"));
3316 EXPECT_TRUE(NavigateToURL(shell(), main_url));
3317 NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
3318 shell()->web_contents()->GetController());
3319 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
3320 ->GetFrameTree()
3321 ->root();
3322
3323 // Verify that the inner iframe was able to load.
3324 ASSERT_EQ(1U, root->child_count());
3325 ASSERT_EQ(1U, root->child_at(0)->child_count());
3326 ASSERT_EQ(0U, root->child_at(0)->child_at(0)->child_count());
3327 EXPECT_EQ(main_url, root->current_url());
3328 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3329 EXPECT_EQ(inner_url, root->child_at(0)->child_at(0)->current_url());
3330
3331 EXPECT_EQ(1, controller.GetEntryCount());
3332 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
3333 NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
3334
3335 // The entry should have FrameNavigationEntries for the subframes.
3336 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3337 ASSERT_EQ(1U, entry->root_node()->children.size());
3338 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3339 EXPECT_EQ(inner_url,
3340 entry->root_node()->children[0]->children[0]->frame_entry->url());
3341 }
3342
3343 // Set a value in the form which will be stored in the PageState.
3344 EXPECT_TRUE(
3345 ExecuteScript(root->child_at(0)->child_at(0),
3346 "document.getElementById('itext').value = 'modified';"));
3347
3348 // 2. Navigate the main frame same-site, destroying the subframes.
3349 GURL main_url_2(embedded_test_server()->GetURL(
3350 "/navigation_controller/simple_page_1.html"));
3351 EXPECT_TRUE(NavigateToURL(shell(), main_url_2));
3352 ASSERT_EQ(0U, root->child_count());
3353 EXPECT_EQ(main_url_2, root->current_url());
3354
3355 EXPECT_EQ(2, controller.GetEntryCount());
3356 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
3357
3358 // 3. Go back, recreating the subframes.
3359 {
3360 TestNavigationObserver back_load_observer(shell()->web_contents());
3361 controller.GoBack();
3362 back_load_observer.Wait();
3363 }
3364 ASSERT_EQ(1U, root->child_count());
3365 // TODO(creis): This line is unexpectedly failing in PlzNavigate, so the test
3366 // is disabled there for now.
3367 ASSERT_EQ(1U, root->child_at(0)->child_count());
3368 ASSERT_EQ(0U, root->child_at(0)->child_at(0)->child_count());
3369 EXPECT_EQ(main_url, root->current_url());
3370 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3371
3372 // Verify that the inner iframe went to the correct URL.
3373 EXPECT_EQ(inner_url, root->child_at(0)->child_at(0)->current_url());
3374
3375 EXPECT_EQ(2, controller.GetEntryCount());
3376 EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
3377 EXPECT_EQ(entry, controller.GetLastCommittedEntry());
3378
3379 // The entry should have FrameNavigationEntries for the subframes.
3380 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3381 ASSERT_EQ(1U, entry->root_node()->children.size());
3382 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3383 EXPECT_EQ(inner_url,
3384 entry->root_node()->children[0]->children[0]->frame_entry->url());
3385 }
3386
3387 // With injected iframe srcdoc pages, we do restore form values from
3388 // PageState.
3389 std::string form_value;
3390 EXPECT_TRUE(
3391 ExecuteScriptAndExtractString(root->child_at(0)->child_at(0),
3392 "window.domAutomationController.send("
3393 "document.getElementById('itext').value);",
3394 &form_value));
3395 EXPECT_EQ("modified", form_value);
3396 }
3397
3398 // Verify that we can load about:blank in an iframe when going back to a page,
3399 // if that iframe did not originally have about:blank in it. See
3400 // https://crbug.com/657896.
3401 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
3402 FrameNavigationEntry_RecreatedSubframeToBlank) {
3403 // 1. Start on a page with a data iframe.
3404 GURL main_url(embedded_test_server()->GetURL(
3405 "/navigation_controller/page_with_data_iframe.html"));
3406 GURL data_url("data:text/html,Subframe");
3407 EXPECT_TRUE(NavigateToURL(shell(), main_url));
3408 NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
3409 shell()->web_contents()->GetController());
3410 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
3411 ->GetFrameTree()
3412 ->root();
3413 ASSERT_EQ(1U, root->child_count());
3414 ASSERT_EQ(0U, root->child_at(0)->child_count());
3415 EXPECT_EQ(main_url, root->current_url());
3416 EXPECT_EQ(data_url, root->child_at(0)->current_url());
3417
3418 // 2. Navigate the subframe to about:blank.
3419 GURL blank_url(url::kAboutBlankURL);
3420 NavigateFrameToURL(root->child_at(0), blank_url);
3421 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3422 EXPECT_EQ(2, controller.GetEntryCount());
3423 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
3424 NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
3425
3426 // The entry should have a FrameNavigationEntry for the blank subframe.
3427 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3428 ASSERT_EQ(1U, entry->root_node()->children.size());
3429 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3430 }
3431
3432 // 3. Navigate the main frame, destroying the frames.
3433 GURL main_url_2(embedded_test_server()->GetURL(
3434 "/navigation_controller/simple_page_1.html"));
3435 EXPECT_TRUE(NavigateToURL(shell(), main_url_2));
3436 ASSERT_EQ(0U, root->child_count());
3437 EXPECT_EQ(main_url_2, root->current_url());
3438
3439 EXPECT_EQ(3, controller.GetEntryCount());
3440 EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
3441
3442 // 3. Go back, recreating the iframe.
3443 {
3444 TestNavigationObserver back_load_observer(shell()->web_contents());
3445 controller.GoBack();
3446 back_load_observer.Wait();
3447 }
3448 ASSERT_EQ(1U, root->child_count());
3449 EXPECT_EQ(main_url, root->current_url());
3450 EXPECT_EQ(blank_url, root->child_at(0)->current_url());
3451
3452 EXPECT_EQ(3, controller.GetEntryCount());
3453 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
3454 EXPECT_EQ(entry, controller.GetLastCommittedEntry());
3455
3456 // The entry should have a FrameNavigationEntry for the blank subframe.
3457 if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
3458 ASSERT_EQ(1U, entry->root_node()->children.size());
3459 EXPECT_EQ(blank_url, entry->root_node()->children[0]->frame_entry->url());
3460 }
3461 }
3462
3216 // Ensure we don't crash if an onload handler removes an about:blank frame after 3463 // Ensure we don't crash if an onload handler removes an about:blank frame after
3217 // recreating it on a back/forward. See https://crbug.com/638166. 3464 // recreating it on a back/forward. See https://crbug.com/638166.
3218 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, 3465 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
3219 FrameNavigationEntry_RemoveRecreatedBlankSubframe) { 3466 FrameNavigationEntry_RemoveRecreatedBlankSubframe) {
3220 // 1. Start on a page that removes its about:blank iframe during onload. 3467 // 1. Start on a page that removes its about:blank iframe during onload.
3221 GURL main_url(embedded_test_server()->GetURL( 3468 GURL main_url(embedded_test_server()->GetURL(
3222 "/navigation_controller/remove_blank_iframe_on_load.html")); 3469 "/navigation_controller/remove_blank_iframe_on_load.html"));
3223 GURL blank_url(url::kAboutBlankURL); 3470 GURL blank_url(url::kAboutBlankURL);
3224 EXPECT_TRUE(NavigateToURL(shell(), main_url)); 3471 EXPECT_TRUE(NavigateToURL(shell(), main_url));
3225 NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>( 3472 NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
(...skipping 2155 matching lines...) Expand 10 before | Expand all | Expand 10 after
5381 subframe_delayer.WaitForNavigationFinished(); 5628 subframe_delayer.WaitForNavigationFinished();
5382 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex()); 5629 EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
5383 EXPECT_EQ(url_a, root->current_url()); 5630 EXPECT_EQ(url_a, root->current_url());
5384 EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url()); 5631 EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url());
5385 5632
5386 // Let the main frame commit. 5633 // Let the main frame commit.
5387 mainframe_delayer.WaitForNavigationFinished(); 5634 mainframe_delayer.WaitForNavigationFinished();
5388 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); 5635 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
5389 EXPECT_EQ(2, controller.GetLastCommittedEntryIndex()); 5636 EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
5390 EXPECT_EQ(url_b, root->current_url()); 5637 EXPECT_EQ(url_b, root->current_url());
5391 5638 EXPECT_EQ(frame_url_b1, root->child_at(0)->current_url());
5392 // TODO(creis): The child's current_url should be about:blank, but we're not
5393 // currently getting a commit in this case. For now, we'll lack a commit for
5394 // this frame, similar to the slow URL case. See https://crbug.com/626416.
5395 if (SiteIsolationPolicy::UseSubframeNavigationEntries())
5396 EXPECT_TRUE(root->child_at(0)->current_url().is_empty());
5397 else
5398 EXPECT_EQ(frame_url_b1, root->child_at(0)->current_url());
5399 5639
5400 // Check the PageState of the previous entry to ensure it isn't corrupted. 5640 // Check the PageState of the previous entry to ensure it isn't corrupted.
5401 NavigationEntry* entry = controller.GetEntryAtIndex(1); 5641 NavigationEntry* entry = controller.GetEntryAtIndex(1);
5402 EXPECT_EQ(url_a, entry->GetURL()); 5642 EXPECT_EQ(url_a, entry->GetURL());
5403 ExplodedPageState exploded_state; 5643 ExplodedPageState exploded_state;
5404 EXPECT_TRUE( 5644 EXPECT_TRUE(
5405 DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state)); 5645 DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state));
5406 EXPECT_EQ(url_a, GURL(exploded_state.top.url_string.string())); 5646 EXPECT_EQ(url_a, GURL(exploded_state.top.url_string.string()));
5407 EXPECT_EQ(frame_url_a2, 5647 EXPECT_EQ(frame_url_a2,
5408 GURL(exploded_state.top.children.at(0).url_string.string())); 5648 GURL(exploded_state.top.children.at(0).url_string.string()));
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after
6095 &headers)); 6335 &headers));
6096 6336
6097 // Verify the Origin and Referer headers. 6337 // Verify the Origin and Referer headers.
6098 EXPECT_THAT(headers, ::testing::HasSubstr("Origin: null")); 6338 EXPECT_THAT(headers, ::testing::HasSubstr("Origin: null"));
6099 EXPECT_THAT(headers, 6339 EXPECT_THAT(headers,
6100 ::testing::ContainsRegex( 6340 ::testing::ContainsRegex(
6101 "Referer: http://a.com:.*/form_that_posts_cross_site.html")); 6341 "Referer: http://a.com:.*/form_that_posts_cross_site.html"));
6102 } 6342 }
6103 6343
6104 } // namespace content 6344 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/browser/frame_host/navigation_entry_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698