|  | // Copyright 2015 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ | 
|  | #define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ | 
|  |  | 
|  | #include "base/feature_list.h" | 
|  | #include "base/functional/callback.h" | 
|  | #include "base/memory/ref_counted.h" | 
|  | #include "base/memory/weak_ptr.h" | 
|  | #include "base/task/single_thread_task_runner.h" | 
|  | #include "content/public/browser/navigation_throttle.h" | 
|  |  | 
|  | namespace content { | 
|  | class NavigationHandle; | 
|  | class NavigationThrottleRegistry; | 
|  | } | 
|  |  | 
|  | namespace navigation_interception { | 
|  |  | 
|  | BASE_DECLARE_FEATURE(kAsyncCheck); | 
|  |  | 
|  | enum class SynchronyMode { | 
|  | // Support async interception in some cases (See ShouldCheckAsynchronously). | 
|  | kAsync, | 
|  | // Only support synchronous interception. | 
|  | kSync | 
|  | }; | 
|  |  | 
|  | // This class allows the provider of the Callback to selectively ignore top | 
|  | // level navigations. This is a UI thread class. | 
|  | class InterceptNavigationThrottle : public content::NavigationThrottle { | 
|  | public: | 
|  | typedef base::OnceCallback<void(bool)> ResultCallback; | 
|  | typedef base::RepeatingCallback<void( | 
|  | content::NavigationHandle* /* navigation_handle */, | 
|  | bool should_run_async, | 
|  | ResultCallback)> | 
|  | CheckCallback; | 
|  |  | 
|  | InterceptNavigationThrottle( | 
|  | content::NavigationThrottleRegistry& registry, | 
|  | CheckCallback should_ignore_callback, | 
|  | SynchronyMode async_mode, | 
|  | std::optional<base::RepeatingClosure> request_finish_async_work_callback); | 
|  |  | 
|  | InterceptNavigationThrottle(const InterceptNavigationThrottle&) = delete; | 
|  | InterceptNavigationThrottle& operator=(const InterceptNavigationThrottle&) = | 
|  | delete; | 
|  |  | 
|  | ~InterceptNavigationThrottle() override; | 
|  |  | 
|  | // content::NavigationThrottle implementation: | 
|  | ThrottleCheckResult WillStartRequest() override; | 
|  | ThrottleCheckResult WillRedirectRequest() override; | 
|  | ThrottleCheckResult WillProcessResponse() override; | 
|  | const char* GetNameForLogging() override; | 
|  |  | 
|  | private: | 
|  | friend class InterceptNavigationThrottleTest; | 
|  | ThrottleCheckResult CheckIfShouldIgnoreNavigation(); | 
|  | void OnCheckComplete(bool should_ignore); | 
|  | void RequestFinishPendingCheck(); | 
|  |  | 
|  | bool ShouldCheckAsynchronously() const; | 
|  |  | 
|  | content::NavigationThrottle::ThrottleCheckResult Defer(); | 
|  |  | 
|  | base::WeakPtr<InterceptNavigationThrottle> GetWeakPtrForTesting(); | 
|  |  | 
|  | // This callback should be called at the start of navigation and every | 
|  | // redirect, until |should_ignore_| is true. | 
|  | // Note: the callback can delete |this|. | 
|  | CheckCallback should_ignore_callback_; | 
|  |  | 
|  | // This callback will be called if a redirect comes in before the previous | 
|  | // should_ignore_callback_ completes, and requires that the outstanding | 
|  | // should_ignore_callback_ completes before returning. | 
|  | std::optional<base::RepeatingClosure> request_finish_async_work_callback_; | 
|  |  | 
|  | // Note that the CheckCallback currently has thread affinity on the Java side. | 
|  | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | 
|  |  | 
|  | const SynchronyMode mode_ = SynchronyMode::kSync; | 
|  |  | 
|  | // Whether the navigation should be ignored. Updated at every redirect. | 
|  | bool should_ignore_ = false; | 
|  |  | 
|  | // Whether a should ignore check is in progress. | 
|  | bool pending_check_ = false; | 
|  |  | 
|  | // Whether a navigation is being deferred because of an outstanding should | 
|  | // ignore check. | 
|  | bool deferring_ = false; | 
|  |  | 
|  | // True if a redirect is doing the deferring. | 
|  | bool deferring_redirect_ = false; | 
|  |  | 
|  | base::TimeTicks defer_start_; | 
|  |  | 
|  | // Tracks whether we're in a synchronous intercept navigation check so we can | 
|  | // crash if we're deleted during the check and get a stack trace. | 
|  | bool in_sync_check_ = false; | 
|  |  | 
|  | base::WeakPtrFactory<InterceptNavigationThrottle> weak_factory_{this}; | 
|  | }; | 
|  |  | 
|  | }  // namespace navigation_interception | 
|  |  | 
|  | #endif  // COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ |