| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_ |
| #define IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_ |
| |
| #include "base/functional/callback.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/memory/weak_ptr.h" |
| #import "ios/web/public/navigation/web_state_policy_decider.h" |
| |
| namespace web { |
| |
| // Tracks responses received from WebStatePolicyDeciders for calls to |
| // shouldAllowResponse(), maintaining the current result based on decisions |
| // received so far, and calling a callback once all decisions have been |
| // received. If all decisions are PolicyDecision::Allow, the final result is |
| // also Allow. If at least one decision is PolicyDecision::Cancel, the final |
| // result is Cancel. Otherwise, if at least one decision is |
| // CancelAndDisplayError, the final result is also CancelAndDisplayError, with |
| // the error associated with the first such decision. If this is destroyed |
| // before all decisions have been received and the callback has not yet been |
| // invoked, the callback is invoked with PolicyDecision::Cancel. |
| class PolicyDecisionStateTracker final { |
| public: |
| // Constructor that takes a `callback` to be called once all decisions have |
| // been received. |
| PolicyDecisionStateTracker( |
| WebStatePolicyDecider::PolicyDecisionCallback callback); |
| |
| ~PolicyDecisionStateTracker(); |
| |
| // Called by each WebStatePolicyDecider with its `decision`. |
| void OnSinglePolicyDecisionReceived( |
| WebStatePolicyDecider::PolicyDecision decision); |
| |
| // Returns true if the final result has already been determined. This means |
| // that either every decider has provided a decision, or the decisions |
| // received so far mean that the final result won't change no matter what |
| // other decisions are received. |
| bool DeterminedFinalResult(); |
| |
| // Called once all WebStatePolicyDeciders have been asked for a decision, |
| // where `num_decisions_requested` is the number of WebStatePolicyDeciders |
| // that have been asked for a decision. |
| void FinishedRequestingDecisions(int num_decisions_requested); |
| |
| private: |
| // Called once, after all WebStatePolicyDeciders have provided a decision or |
| // after the decisions received so far have already determined the final |
| // result. |
| void OnFinalResultDetermined(); |
| |
| // Called once with the final result. |
| base::OnceCallback<void(WebStatePolicyDecider::PolicyDecision)> callback_; |
| |
| // The current result, based on the decisions received so far. |
| WebStatePolicyDecider::PolicyDecision result_ = |
| WebStatePolicyDecider::PolicyDecision::Allow(); |
| |
| // The number of WebStatePolicyDeciders that have provided a decision. |
| int num_decisions_received_ = 0; |
| |
| // Called after each decision is received. Initially, this is a no-op. Once |
| // all decisions have been requested, this is changed to a BarrierClosure |
| // that handles invoking `callback_` after receiving the remaining |
| // outstanding decisions. |
| base::RepeatingClosure decision_closure_ = base::DoNothing(); |
| |
| base::WeakPtrFactory<PolicyDecisionStateTracker> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace web |
| |
| #endif // IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_ |