blob: f3a1f47641560f0e77ad6754108079be7e7bf452 [file] [log] [blame]
// 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.
#ifndef IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_
#define IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_
#include "base/callback.h"
#include "base/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
: public base::SupportsWeakPtr<PolicyDecisionStateTracker> {
public:
// Constructor that takes a |callback| to be called once all decisions have
// been received.
PolicyDecisionStateTracker(
base::OnceCallback<void(WebStatePolicyDecider::PolicyDecision)> 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();
};
} // namespace web
#endif // IOS_WEB_WEB_STATE_POLICY_DECISION_STATE_TRACKER_H_