| Index: components/safe_browsing/request_checker.h | 
| diff --git a/components/safe_browsing/request_checker.h b/components/safe_browsing/request_checker.h | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..1d2409c8a0731132973e12cd9bb16486e32ee87a | 
| --- /dev/null | 
| +++ b/components/safe_browsing/request_checker.h | 
| @@ -0,0 +1,196 @@ | 
| +// Copyright 2017 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 COMPONENTS_SAFE_BROWSING_REQUEST_CHECKER_H_ | 
| +#define COMPONENTS_SAFE_BROWSING_REQUEST_CHECKER_H_ | 
| + | 
| +#include <vector> | 
| + | 
| +#include "base/callback_forward.h" | 
| +#include "base/macros.h" | 
| +#include "base/memory/ref_counted.h" | 
| +#include "base/memory/weak_ptr.h" | 
| +#include "base/time/time.h" | 
| +#include "base/timer/timer.h" | 
| +#include "components/safe_browsing_db/database_manager.h" | 
| +#include "content/public/browser/web_contents.h" | 
| +#include "content/public/common/resource_type.h" | 
| +#include "net/log/net_log_event_type.h" | 
| +#include "net/log/net_log_with_source.h" | 
| +#include "url/gurl.h" | 
| + | 
| +namespace content { | 
| +class WebContents; | 
| +} | 
| + | 
| +namespace net { | 
| +class URLRequest; | 
| +} | 
| + | 
| +namespace security_interstitials { | 
| +struct UnsafeResource; | 
| +} | 
| + | 
| +namespace safe_browsing { | 
| + | 
| +class BaseUIManager; | 
| +class ScopedTimeoutForTesting; | 
| + | 
| +class RequestChecker final : public SafeBrowsingDatabaseManager::Client { | 
| + public: | 
| +  enum DeferDecision { | 
| +    DEFER,                // Should wait for permission to proceed | 
| +    PROCEED_SKIPPED,      // ResourceType is exempted from checking | 
| +    PROCEED_SAFE,         // Checked and safe | 
| +    PROCEED_ALWAYS_ASYNC  // Checks are always async on this platform | 
| +  }; | 
| + | 
| +  class Delegate { | 
| +   public: | 
| +    // This duplicates the definition of | 
| +    // content::ResourceRequestInfo::WebContentsGetter to avoid having a | 
| +    // dependency on ResourceRequestInfo. | 
| +    using WebContentsGetter = base::Callback<content::WebContents*(void)>; | 
| + | 
| +    Delegate() {} | 
| +    virtual ~Delegate() {} | 
| +    virtual void MaybeDestroyPrerenderContents( | 
| +        const net::URLRequest* request) = 0; | 
| +    virtual WebContentsGetter GetWebContentsGetterForRequest( | 
| +        const net::URLRequest* request) const = 0; | 
| +    virtual void StartDisplayingBlockingPage( | 
| +        const security_interstitials::UnsafeResource& resource, | 
| +        scoped_refptr<BaseUIManager> ui_manager) = 0; | 
| +    virtual void CancelResourceLoad() = 0; | 
| +    virtual void ResumeResourceRequest() = 0; | 
| + | 
| +   private: | 
| +    DISALLOW_COPY_AND_ASSIGN(Delegate); | 
| +  }; | 
| + | 
| +  RequestChecker(const net::URLRequest* request, | 
| +                 content::ResourceType resource_type, | 
| +                 scoped_refptr<SafeBrowsingDatabaseManager> database_manager, | 
| +                 scoped_refptr<BaseUIManager> ui_manager, | 
| +                 Delegate* delegate); | 
| +  ~RequestChecker() final; | 
| + | 
| +  // Should be called once to start checking the URL that was passed to the | 
| +  // constructor. | 
| +  DeferDecision CheckNewRequest(); | 
| + | 
| +  // Can be called 0 or more times. Must not be called before CheckNewRequest(). | 
| +  // If the previous call to CheckNewRequest() or CheckRedirect() returned | 
| +  // DEFER, must not be called until Delegate::ResumeResourceRequest() has been | 
| +  // called. | 
| +  DeferDecision CheckRedirect(const GURL& new_url); | 
| + | 
| +  // Should be called once. Must not be called before | 
| +  // CheckNewRequest(). CheckRedirect() must not be called after | 
| +  // ShouldDeferResponse(). As with CheckRedirect(), if the previous call to | 
| +  // CheckNewRequest() or CheckRedirect() returned DEFER, ShouldDeferResponse() | 
| +  // must not be called until Delegate::ResumeResourceRequest() has been called. | 
| +  DeferDecision ShouldDeferResponse(); | 
| + | 
| +  // SafeBrowsingDatabaseManager::Client implementation (called on IO thread): | 
| +  void OnCheckBrowseUrlResult(const GURL& url, | 
| +                              SBThreatType threat_type, | 
| +                              const ThreatMetadata& metadata) final; | 
| + | 
| + private: | 
| +  // Describes what phase of the check a throttle is in. | 
| +  enum State { | 
| +    // Haven't started checking or checking is complete. Not deferred. | 
| +    STATE_NONE, | 
| +    // We have one outstanding URL-check. Could be deferred. | 
| +    STATE_CHECKING_URL, | 
| +    // We're displaying a blocking page. Could be deferred. | 
| +    STATE_DISPLAYING_BLOCKING_PAGE, | 
| +  }; | 
| + | 
| +  // Describes what stage of the request got paused by the check. | 
| +  enum DeferState { | 
| +    DEFERRED_NONE, | 
| +    DEFERRED_START, | 
| +    DEFERRED_REDIRECT, | 
| +    DEFERRED_UNCHECKED_REDIRECT,  // unchecked_redirect_url_ is populated. | 
| +    DEFERRED_PROCESSING, | 
| +  }; | 
| + | 
| +  void OnBlockingPageComplete(bool proceed); | 
| + | 
| +  // Starts running |url| through the safe browsing check. If it returns DEFER | 
| +  // then one of the Delegate methods will be called asynchronously. If one | 
| +  // PROCEED_SKIPPED or PROCEED_SAFE is returned then it will take no further | 
| +  // action. Never returns PROCEED_ALWAYS_ASYNC. | 
| +  DeferDecision CheckUrl(const GURL& url); | 
| + | 
| +  // Callback for when the safe browsing check (which was initiated by | 
| +  // StartCheckingUrl()) has taken longer than kCheckUrlTimeoutMs. | 
| +  void OnCheckUrlTimeout(); | 
| + | 
| +  void ResumeRequest(); | 
| + | 
| +  // For marking network events.  |name| and |value| can be null. | 
| +  void BeginNetLogEvent(net::NetLogEventType type, | 
| +                        const GURL& url, | 
| +                        const char* name, | 
| +                        const char* value); | 
| +  void EndNetLogEvent(net::NetLogEventType type, | 
| +                      const char* name, | 
| +                      const char* value); | 
| + | 
| +  State state_; | 
| +  DeferState defer_state_; | 
| +  const content::ResourceType resource_type_; | 
| + | 
| +  // The result of the most recent safe browsing check. Only valid to read this | 
| +  // when state_ != STATE_CHECKING_URL. | 
| +  safe_browsing::SBThreatType threat_type_; | 
| + | 
| +  // The time when we started deferring the request. | 
| +  base::TimeTicks defer_start_time_; | 
| + | 
| +  const net::URLRequest* request_; | 
| + | 
| +  scoped_refptr<BaseUIManager> ui_manager_; | 
| + | 
| +  scoped_refptr<SafeBrowsingDatabaseManager> database_manager_; | 
| + | 
| +  // Timer to abort the safe browsing check if it takes too long. | 
| +  base::OneShotTimer timer_; | 
| + | 
| +  // The redirect chain for this resource | 
| +  std::vector<GURL> redirect_urls_; | 
| + | 
| +  // If in DEFERRED_UNCHECKED_REDIRECT state, this is the | 
| +  // URL we still need to check before resuming. | 
| +  GURL unchecked_redirect_url_; | 
| +  GURL url_being_checked_; | 
| + | 
| +  net::NetLogWithSource net_log_with_source_; | 
| +  Delegate* delegate_; | 
| + | 
| +  base::WeakPtrFactory<RequestChecker> weak_factory_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(RequestChecker); | 
| +}; | 
| + | 
| +// This class can be used to locally change the timeout for checks. Thread | 
| +// hostile. | 
| +class ScopedTimeoutForTesting { | 
| + public: | 
| +  explicit ScopedTimeoutForTesting(int new_timeout_ms); | 
| +  ScopedTimeoutForTesting(ScopedTimeoutForTesting&& rhs); | 
| +  ~ScopedTimeoutForTesting(); | 
| + | 
| + private: | 
| +  int original_timeout_ms_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(ScopedTimeoutForTesting); | 
| +}; | 
| + | 
| +}  // namespace safe_browsing | 
| + | 
| +#endif  // COMPONENTS_SAFE_BROWSING_REQUEST_CHECKER_H_ | 
|  |