123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h"
- #include "ios/components/security_interstitials/ios_security_interstitial_page.h"
- #import "ios/web/public/test/fakes/fake_navigation_context.h"
- #import "ios/web/public/test/fakes/fake_web_state.h"
- #include "testing/platform_test.h"
- #include "url/gurl.h"
- #if !defined(__has_feature) || !__has_feature(objc_arc)
- #error "This file requires ARC support."
- #endif
- namespace security_interstitials {
- class TestInterstitialPage : public IOSSecurityInterstitialPage {
- public:
- // |*destroyed_tracker| is set to true in the destructor.
- TestInterstitialPage(web::WebState* web_state,
- const GURL& request_url,
- bool* destroyed_tracker)
- : IOSSecurityInterstitialPage(web_state,
- request_url,
- /*argument_name=*/nullptr),
- destroyed_tracker_(destroyed_tracker) {}
- ~TestInterstitialPage() override {
- if (destroyed_tracker_)
- *destroyed_tracker_ = true;
- }
- private:
- void HandleCommand(SecurityInterstitialCommand command,
- const GURL& origin_url,
- bool user_is_interacting,
- web::WebFrame* sender_frame) override {}
- bool ShouldCreateNewNavigation() const override { return false; }
- void PopulateInterstitialStrings(
- base::Value::Dict& load_time_data) const override {}
- bool* destroyed_tracker_ = nullptr;
- };
- class IOSBlockingPageTabHelperTest : public PlatformTest {
- protected:
- IOSBlockingPageTabHelperTest() {
- IOSBlockingPageTabHelper::CreateForWebState(&web_state_);
- }
- std::unique_ptr<web::NavigationContext> CreateContext(bool committed,
- bool is_same_document) {
- std::unique_ptr<web::FakeNavigationContext> context =
- std::make_unique<web::FakeNavigationContext>();
- context->SetHasCommitted(committed);
- context->SetIsSameDocument(is_same_document);
- return context;
- }
- IOSBlockingPageTabHelper* helper() {
- return IOSBlockingPageTabHelper::FromWebState(&web_state_);
- }
- // Creates a blocking page and associates it with |context|'s navigation ID
- // in the tab helper. Returns the created blocking page. |destroyed_tracker|
- // is an out-parameter that is reset to true when the blocking page is
- // destroyed.
- IOSSecurityInterstitialPage* CreateAssociatedBlockingPage(
- web::NavigationContext* context,
- bool* destroyed_tracker) {
- std::unique_ptr<IOSSecurityInterstitialPage> passed_blocking_page =
- std::make_unique<TestInterstitialPage>(&web_state_, GURL(),
- destroyed_tracker);
- IOSSecurityInterstitialPage* blocking_page = passed_blocking_page.get();
- helper()->AssociateBlockingPage(context->GetNavigationId(),
- std::move(passed_blocking_page));
- return blocking_page;
- }
- web::FakeWebState web_state_;
- };
- // Tests that the helper properly handles the lifetime of a single blocking
- // page, interleaved with other navigations.
- TEST_F(IOSBlockingPageTabHelperTest, SingleBlockingPage) {
- std::unique_ptr<web::NavigationContext> blocking_page_context =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- bool blocking_page_destroyed = false;
- CreateAssociatedBlockingPage(blocking_page_context.get(),
- &blocking_page_destroyed);
- // Test that a same-document navigation doesn't destroy the blocking page if
- // its navigation hasn't committed yet.
- std::unique_ptr<web::NavigationContext> same_document_context =
- CreateContext(/*committed=*/true, /*is_same_document=*/true);
- web_state_.OnNavigationFinished(same_document_context.get());
- EXPECT_FALSE(blocking_page_destroyed);
- // Test that a committed (non-same-document) navigation doesn't destroy the
- // blocking page if its navigation hasn't committed yet.
- std::unique_ptr<web::NavigationContext> committed_context1 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- web_state_.OnNavigationFinished(committed_context1.get());
- EXPECT_FALSE(blocking_page_destroyed);
- // Simulate committing the interstitial.
- web_state_.OnNavigationFinished(blocking_page_context.get());
- EXPECT_FALSE(blocking_page_destroyed);
- // Test that a subsequent committed navigation releases the blocking page
- // stored for the currently committed navigation.
- std::unique_ptr<web::NavigationContext> committed_context2 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- web_state_.OnNavigationFinished(committed_context2.get());
- EXPECT_TRUE(blocking_page_destroyed);
- }
- // Tests that the helper properly handles the lifetime of multiple blocking
- // pages, committed in a different order than they are created.
- TEST_F(IOSBlockingPageTabHelperTest, MultipleBlockingPage) {
- // Simulate associating the first interstitial.
- std::unique_ptr<web::NavigationContext> context1 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- bool blocking_page1_destroyed = false;
- CreateAssociatedBlockingPage(context1.get(), &blocking_page1_destroyed);
- // Simulate commiting the first interstitial.
- web_state_.OnNavigationFinished(context1.get());
- EXPECT_FALSE(blocking_page1_destroyed);
- // Associate the second interstitial.
- std::unique_ptr<web::NavigationContext> context2 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- bool blocking_page2_destroyed = false;
- CreateAssociatedBlockingPage(context2.get(), &blocking_page2_destroyed);
- EXPECT_FALSE(blocking_page1_destroyed);
- EXPECT_FALSE(blocking_page2_destroyed);
- // Associate the third interstitial.
- std::unique_ptr<web::NavigationContext> context3 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- bool blocking_page3_destroyed = false;
- CreateAssociatedBlockingPage(context3.get(), &blocking_page3_destroyed);
- EXPECT_FALSE(blocking_page1_destroyed);
- EXPECT_FALSE(blocking_page2_destroyed);
- EXPECT_FALSE(blocking_page3_destroyed);
- // Simulate committing the third interstitial.
- web_state_.OnNavigationFinished(context3.get());
- EXPECT_TRUE(blocking_page1_destroyed);
- EXPECT_FALSE(blocking_page2_destroyed);
- EXPECT_FALSE(blocking_page3_destroyed);
- // Simulate committing the second interstitial.
- web_state_.OnNavigationFinished(context2.get());
- EXPECT_TRUE(blocking_page1_destroyed);
- EXPECT_FALSE(blocking_page2_destroyed);
- EXPECT_TRUE(blocking_page3_destroyed);
- // Test that a subsequent committed navigation releases the last blocking
- // page.
- std::unique_ptr<web::NavigationContext> committed_context4 =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- web_state_.OnNavigationFinished(committed_context4.get());
- EXPECT_TRUE(blocking_page2_destroyed);
- }
- // Tests that the helper properly handles a navigation that finishes without
- // committing.
- TEST_F(IOSBlockingPageTabHelperTest, NavigationDoesNotCommit) {
- std::unique_ptr<web::NavigationContext> committed_context =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- bool committed_blocking_page_destroyed = false;
- CreateAssociatedBlockingPage(committed_context.get(),
- &committed_blocking_page_destroyed);
- web_state_.OnNavigationFinished(committed_context.get());
- EXPECT_FALSE(committed_blocking_page_destroyed);
- // Simulate a navigation that does not commit.
- std::unique_ptr<web::NavigationContext> non_committed_context =
- CreateContext(/*committed=*/false, /*is_same_document=*/false);
- bool non_committed_blocking_page_destroyed = false;
- CreateAssociatedBlockingPage(non_committed_context.get(),
- &non_committed_blocking_page_destroyed);
- web_state_.OnNavigationFinished(non_committed_context.get());
- // The blocking page for the non-committed navigation should have been cleaned
- // up, but the one for the previous committed navigation should still be
- // around.
- EXPECT_TRUE(non_committed_blocking_page_destroyed);
- EXPECT_FALSE(committed_blocking_page_destroyed);
- // When a navigation does commit, the previous one should be cleaned up.
- std::unique_ptr<web::NavigationContext> next_committed_context =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- web_state_.OnNavigationFinished(next_committed_context.get());
- EXPECT_TRUE(committed_blocking_page_destroyed);
- }
- // Tests that a blocking page that is associated with a navigation ID after the
- // navigation is committed is correctly used as the current blocking page for
- // the last commited navigation ID.
- TEST_F(IOSBlockingPageTabHelperTest, BlockingPageAssociatedAfterCommit) {
- // Commit the navigation, then associate the blocking page.
- std::unique_ptr<web::NavigationContext> context =
- CreateContext(/*committed=*/true, /*is_same_document=*/false);
- web_state_.OnNavigationFinished(context.get());
- IOSSecurityInterstitialPage* page =
- CreateAssociatedBlockingPage(context.get(), nullptr);
- // Verify that the blocking page is used as the current page.
- EXPECT_EQ(page, helper()->GetCurrentBlockingPage());
- }
- } // namespace security_interstitials
|