| // Copyright 2020 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/web/web_state/policy_decision_state_tracker.h" |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "base/optional.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "testing/platform_test.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace web { |
| |
| class PolicyDecisionStateTrackerTest : public PlatformTest { |
| public: |
| PolicyDecisionStateTrackerTest() |
| : policy_decision_state_tracker_( |
| base::Bind(&PolicyDecisionStateTrackerTest::OnDecisionDetermined, |
| base::Unretained(this))) {} |
| |
| void OnDecisionDetermined( |
| WebStatePolicyDecider::PolicyDecision policy_decision) { |
| policy_decision_ = policy_decision; |
| } |
| |
| PolicyDecisionStateTracker policy_decision_state_tracker_; |
| base::Optional<WebStatePolicyDecider::PolicyDecision> policy_decision_; |
| }; |
| |
| // Tests the case where every decision received is to allow the navigation, and |
| // each such decision is received before calling FinishedRequestingDecisions. |
| TEST_F(PolicyDecisionStateTrackerTest, AllAllowSync) { |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| int num_decisions_requested = 3; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| EXPECT_TRUE(policy_decision_->ShouldAllowNavigation()); |
| } |
| |
| // Tests the case where every decision received is to allow the navigation, and |
| // each such decision is received after calling FinishedRequestingDecisions. |
| TEST_F(PolicyDecisionStateTrackerTest, AllAllowAsync) { |
| int num_decisions_requested = 3; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldAllowNavigation()); |
| } |
| |
| // Tests the case where every decision received is to allow the navigation, and |
| // some decisions are received before calling FinishedRequestingDecisions while |
| // the rest of the decisions are received later. |
| TEST_F(PolicyDecisionStateTrackerTest, AllAllowMixed) { |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| int num_decisions_requested = 4; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldAllowNavigation()); |
| } |
| |
| // Tests the case where a decision to cancel the navigation is received before |
| // FinishedRequestingDecisions is called. |
| TEST_F(PolicyDecisionStateTrackerTest, CancelSync) { |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Cancel()); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); |
| EXPECT_FALSE(policy_decision_->ShouldDisplayError()); |
| |
| // Verify that additional calls into |policy_decision_state_tracker_| do not |
| // lead to additional calls to its callback, which would crash since the |
| // callback is a OnceCallback. |
| int num_decisions_requested = 4; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Cancel()); |
| } |
| |
| // Tests the case where a decision to cancel the navigation is received after |
| // FinishedRequestingDecisions is called. |
| TEST_F(PolicyDecisionStateTrackerTest, CancelAsync) { |
| NSError* error = [NSError errorWithDomain:@"ErrorDomain" code:1 userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error)); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| int num_decisions_requested = 4; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| // A decision to cancel without an error should take precedence over the |
| // decision to show an error. |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Cancel()); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); |
| EXPECT_FALSE(policy_decision_->ShouldDisplayError()); |
| |
| // Verify that an additional calls into policy_decision_state_tracker_ do not |
| // lead to additional calls to its callback, which would crash since the |
| // callback is a OnceCallback. |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Cancel()); |
| } |
| |
| // Tests the case where a decision to show an error is received before |
| // FinishedRequestingDecisions is called. |
| TEST_F(PolicyDecisionStateTrackerTest, ShowErrorSync) { |
| NSError* error = [NSError errorWithDomain:@"ErrorDomain" code:1 userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error)); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| int num_decisions_requested = 3; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); |
| EXPECT_TRUE(policy_decision_->ShouldDisplayError()); |
| } |
| |
| // Tests the case where decisions to show an error are received after |
| // FinishedRequestingDecisions is called. |
| TEST_F(PolicyDecisionStateTrackerTest, ShowErrorAsync) { |
| int num_decisions_requested = 3; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| NSError* error1 = [NSError errorWithDomain:@"ErrorDomain" |
| code:1 |
| userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error1)); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| NSError* error2 = [NSError errorWithDomain:@"ErrorDomain" |
| code:2 |
| userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error2)); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); |
| EXPECT_TRUE(policy_decision_->ShouldDisplayError()); |
| |
| // The error received first should take precedence. |
| EXPECT_EQ(policy_decision_->GetDisplayError().code, error1.code); |
| } |
| |
| // Tests the case where decisions to show an error are received both before and |
| // after FinishedRequestingDecisions is called. |
| TEST_F(PolicyDecisionStateTrackerTest, ShowErrorMixed) { |
| NSError* error1 = [NSError errorWithDomain:@"ErrorDomain" |
| code:1 |
| userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error1)); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| int num_decisions_requested = 3; |
| policy_decision_state_tracker_.FinishedRequestingDecisions( |
| num_decisions_requested); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::Allow()); |
| EXPECT_FALSE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_FALSE(policy_decision_); |
| |
| NSError* error2 = [NSError errorWithDomain:@"ErrorDomain" |
| code:2 |
| userInfo:nil]; |
| policy_decision_state_tracker_.OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(error2)); |
| EXPECT_TRUE(policy_decision_state_tracker_.DeterminedFinalResult()); |
| EXPECT_TRUE(policy_decision_); |
| |
| EXPECT_TRUE(policy_decision_->ShouldCancelNavigation()); |
| EXPECT_TRUE(policy_decision_->ShouldDisplayError()); |
| |
| // The error received first should take precedence. |
| EXPECT_EQ(policy_decision_->GetDisplayError().code, error1.code); |
| } |
| |
| } // namespace web |