// Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "libcef/browser/net_service/resource_request_handler_wrapper.h"

#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/browser/context.h"
#include "libcef/browser/net_service/cookie_helper.h"
#include "libcef/browser/net_service/proxy_url_loader_factory.h"
#include "libcef/browser/net_service/resource_handler_wrapper.h"
#include "libcef/browser/net_service/response_filter_wrapper.h"
#include "libcef/browser/resource_context.h"
#include "libcef/browser/thread_util.h"
#include "libcef/common/content_client.h"
#include "libcef/common/net/scheme_registration.h"
#include "libcef/common/net_service/net_service_util.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/response_impl.h"

#include "chrome/common/chrome_features.h"
#include "components/language/core/browser/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/load_flags.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
#include "ui/base/page_transition_types.h"
#include "url/origin.h"

namespace net_service {

namespace {

const int kLoadNoCookiesFlags =
    net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;

class RequestCallbackWrapper : public CefRequestCallback {
 public:
  using Callback = base::OnceCallback<void(bool /* allow */)>;
  explicit RequestCallbackWrapper(Callback callback)
      : callback_(std::move(callback)),
        work_thread_task_runner_(base::SequencedTaskRunnerHandle::Get()) {}

  ~RequestCallbackWrapper() override {
    if (!callback_.is_null()) {
      // Make sure it executes on the correct thread.
      work_thread_task_runner_->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback_), true));
    }
  }

  void Continue(bool allow) override {
    if (!work_thread_task_runner_->RunsTasksInCurrentSequence()) {
      work_thread_task_runner_->PostTask(
          FROM_HERE,
          base::BindOnce(&RequestCallbackWrapper::Continue, this, allow));
      return;
    }
    if (!callback_.is_null()) {
      std::move(callback_).Run(allow);
    }
  }

  void Cancel() override { Continue(false); }

 private:
  Callback callback_;

  scoped_refptr<base::SequencedTaskRunner> work_thread_task_runner_;

  IMPLEMENT_REFCOUNTING(RequestCallbackWrapper);
  DISALLOW_COPY_AND_ASSIGN(RequestCallbackWrapper);
};

std::string GetAcceptLanguageList(content::BrowserContext* browser_context,
                                  CefRefPtr<CefBrowserHostImpl> browser) {
  if (browser) {
    const CefBrowserSettings& browser_settings = browser->settings();
    if (browser_settings.accept_language_list.length > 0) {
      return CefString(&browser_settings.accept_language_list);
    }
  }

  // This defaults to the value from CefRequestContextSettings via
  // browser_prefs::CreatePrefService().
  auto prefs = Profile::FromBrowserContext(browser_context)->GetPrefs();
  return prefs->GetString(language::prefs::kAcceptLanguages);
}

// Match the logic in chrome/browser/net/profile_network_context_service.cc.
std::string ComputeAcceptLanguageFromPref(const std::string& language_pref) {
  std::string accept_languages_str =
      base::FeatureList::IsEnabled(features::kUseNewAcceptLanguageHeader)
          ? net::HttpUtil::ExpandLanguageList(language_pref)
          : language_pref;
  return net::HttpUtil::GenerateAcceptLanguageHeader(accept_languages_str);
}

class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
 public:
  struct RequestState {
    RequestState() {}

    void Reset(CefRefPtr<CefResourceRequestHandler> handler,
               CefRefPtr<CefSchemeHandlerFactory> scheme_factory,
               CefRefPtr<CefRequestImpl> request,
               bool request_was_redirected,
               CancelRequestCallback cancel_callback) {
      handler_ = handler;
      scheme_factory_ = scheme_factory;
      cookie_filter_ = nullptr;
      pending_request_ = request;
      pending_response_ = nullptr;
      request_was_redirected_ = request_was_redirected;
      was_custom_handled_ = false;
      cancel_callback_ = std::move(cancel_callback);
    }

    CefRefPtr<CefResourceRequestHandler> handler_;
    CefRefPtr<CefSchemeHandlerFactory> scheme_factory_;
    CefRefPtr<CefCookieAccessFilter> cookie_filter_;
    CefRefPtr<CefRequestImpl> pending_request_;
    CefRefPtr<CefResponseImpl> pending_response_;
    bool request_was_redirected_ = false;
    bool was_custom_handled_ = false;
    CancelRequestCallback cancel_callback_;
  };

  struct PendingRequest {
    PendingRequest(const RequestId& id,
                   network::ResourceRequest* request,
                   bool request_was_redirected,
                   OnBeforeRequestResultCallback callback,
                   CancelRequestCallback cancel_callback)
        : id_(id),
          request_(request),
          request_was_redirected_(request_was_redirected),
          callback_(std::move(callback)),
          cancel_callback_(std::move(cancel_callback)) {}

    ~PendingRequest() {
      if (cancel_callback_) {
        std::move(cancel_callback_).Run(net::ERR_ABORTED);
      }
    }

    void Run(InterceptedRequestHandlerWrapper* self) {
      self->OnBeforeRequest(id_, request_, request_was_redirected_,
                            std::move(callback_), std::move(cancel_callback_));
    }

    const RequestId id_;
    network::ResourceRequest* const request_;
    const bool request_was_redirected_;
    OnBeforeRequestResultCallback callback_;
    CancelRequestCallback cancel_callback_;
  };

  // Observer to receive notification of CEF context or associated browser
  // destruction. Only one of the *Destroyed() methods will be called.
  class DestructionObserver : public CefBrowserHostImpl::Observer,
                              public CefContext::Observer {
   public:
    explicit DestructionObserver(CefBrowserHostImpl* browser) {
      if (browser) {
        browser_info_ = browser->browser_info();
        browser->AddObserver(this);
      } else {
        CefContext::Get()->AddObserver(this);
      }
    }

    virtual ~DestructionObserver() {
      CEF_REQUIRE_UIT();
      if (!registered_)
        return;

      // Verify that the browser or context still exists before attempting to
      // remove the observer.
      if (browser_info_) {
        auto browser = browser_info_->browser();
        if (browser)
          browser->RemoveObserver(this);
      } else if (CefContext::Get()) {
        // Network requests may be torn down during shutdown, so we can't check
        // CONTEXT_STATE_VALID() here.
        CefContext::Get()->RemoveObserver(this);
      }
    }

    void SetWrapper(base::WeakPtr<InterceptedRequestHandlerWrapper> wrapper) {
      CEF_REQUIRE_IOT();
      wrapper_ = wrapper;
    }

    void OnBrowserDestroyed(CefBrowserHostImpl* browser) override {
      CEF_REQUIRE_UIT();
      browser->RemoveObserver(this);
      registered_ = false;
      browser_info_ = nullptr;
      NotifyOnDestroyed();
    }

    void OnContextDestroyed() override {
      CEF_REQUIRE_UIT();
      CefContext::Get()->RemoveObserver(this);
      registered_ = false;
      NotifyOnDestroyed();
    }

   private:
    void NotifyOnDestroyed() {
      if (wrapper_.MaybeValid()) {
        // This will be a no-op if the WeakPtr is invalid.
        CEF_POST_TASK(
            CEF_IOT,
            base::BindOnce(&InterceptedRequestHandlerWrapper::OnDestroyed,
                           wrapper_));
      }
    }

    scoped_refptr<CefBrowserInfo> browser_info_;
    bool registered_ = true;

    base::WeakPtr<InterceptedRequestHandlerWrapper> wrapper_;
    DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
  };

  // Holds state information for InterceptedRequestHandlerWrapper. State is
  // initialized on the UI thread and later passed to the *Wrapper object on
  // the IO thread.
  struct InitState {
    InitState() {}

    ~InitState() {
      if (destruction_observer_) {
        if (initialized_) {
          // Clear the reference added in
          // InterceptedRequestHandlerWrapper::SetInitialized().
          destruction_observer_->SetWrapper(nullptr);
        }
        DeleteDestructionObserver();
      }
    }

    void Initialize(content::BrowserContext* browser_context,
                    CefRefPtr<CefBrowserHostImpl> browser,
                    CefRefPtr<CefFrame> frame,
                    int render_process_id,
                    int render_frame_id,
                    int frame_tree_node_id,
                    bool is_navigation,
                    bool is_download,
                    const url::Origin& request_initiator) {
      CEF_REQUIRE_UIT();

      browser_context_ = browser_context;
      resource_context_ = static_cast<CefResourceContext*>(
          browser_context->GetResourceContext());
      DCHECK(resource_context_);

      // We register to be notified of CEF context or browser destruction so
      // that we can stop accepting new requests and cancel pending/in-progress
      // requests in a timely manner (e.g. before we start asserting about
      // leaked objects during CEF shutdown).
      destruction_observer_.reset(new DestructionObserver(browser.get()));

      if (browser) {
        // These references will be released in OnDestroyed().
        browser_ = browser;
        frame_ = frame;
      }

      render_process_id_ = render_process_id;
      render_frame_id_ = render_frame_id;
      frame_tree_node_id_ = frame_tree_node_id;
      is_navigation_ = is_navigation;
      is_download_ = is_download;
      request_initiator_ = request_initiator.Serialize();

      // Default values for standard headers.
      accept_language_ = ComputeAcceptLanguageFromPref(
          GetAcceptLanguageList(browser_context, browser));
      DCHECK(!accept_language_.empty());
      user_agent_ = CefContentClient::Get()->browser()->GetUserAgent();
      DCHECK(!user_agent_.empty());
    }

    void DeleteDestructionObserver() {
      DCHECK(destruction_observer_);
      CEF_POST_TASK(
          CEF_UIT,
          base::BindOnce(&InitState::DeleteDestructionObserverOnUIThread,
                         std::move(destruction_observer_)));
    }

    static void DeleteDestructionObserverOnUIThread(
        std::unique_ptr<DestructionObserver> observer) {}

    // Only accessed on the UI thread.
    content::BrowserContext* browser_context_ = nullptr;

    bool initialized_ = false;

    CefRefPtr<CefBrowserHostImpl> browser_;
    CefRefPtr<CefFrame> frame_;
    CefResourceContext* resource_context_ = nullptr;
    int render_process_id_ = 0;
    int render_frame_id_ = -1;
    int frame_tree_node_id_ = -1;
    bool is_navigation_ = true;
    bool is_download_ = false;
    CefString request_initiator_;

    // Default values for standard headers.
    std::string accept_language_;
    std::string user_agent_;

    // Used to receive destruction notification.
    std::unique_ptr<DestructionObserver> destruction_observer_;
  };

  // Manages InterceptedRequestHandlerWrapper initialization. The *Wrapper
  // object is owned by ProxyURLLoaderFactory and may be deleted before
  // SetInitialized() is called.
  struct InitHelper : base::RefCountedThreadSafe<InitHelper> {
   public:
    explicit InitHelper(InterceptedRequestHandlerWrapper* wrapper)
        : wrapper_(wrapper) {}

    void MaybeSetInitialized(std::unique_ptr<InitState> init_state) {
      CEF_POST_TASK(CEF_IOT, base::BindOnce(&InitHelper::SetInitialized, this,
                                            std::move(init_state)));
    }

    void Disconnect() {
      base::AutoLock lock_scope(lock_);
      wrapper_ = nullptr;
    }

   private:
    void SetInitialized(std::unique_ptr<InitState> init_state) {
      base::AutoLock lock_scope(lock_);
      // May be nullptr if the InterceptedRequestHandlerWrapper has already
      // been deleted.
      if (!wrapper_)
        return;
      wrapper_->SetInitialized(std::move(init_state));
      wrapper_ = nullptr;
    }

    base::Lock lock_;
    InterceptedRequestHandlerWrapper* wrapper_;
  };

  InterceptedRequestHandlerWrapper()
      : init_helper_(base::MakeRefCounted<InitHelper>(this)),
        weak_ptr_factory_(this) {}

  ~InterceptedRequestHandlerWrapper() override {
    CEF_REQUIRE_IOT();

    // There should be no in-progress requests during destruction.
    DCHECK(request_map_.empty());

    // Don't continue with initialization if we get deleted before
    // SetInitialized is called asynchronously.
    init_helper_->Disconnect();
  }

  scoped_refptr<InitHelper> init_helper() const { return init_helper_; }

  void SetInitialized(std::unique_ptr<InitState> init_state) {
    CEF_REQUIRE_IOT();
    DCHECK(!init_state_);
    init_state_ = std::move(init_state);

    // Check that the CEF context or associated browser was not destroyed
    // between the calls to Initialize and SetInitialized, in which case
    // we won't get an OnDestroyed callback from DestructionObserver.
    if (init_state_->browser_) {
      if (!init_state_->browser_->browser_info()->browser()) {
        OnDestroyed();
        return;
      }
    } else if (!CONTEXT_STATE_VALID()) {
      OnDestroyed();
      return;
    }

    init_state_->initialized_ = true;
    init_state_->destruction_observer_->SetWrapper(
        weak_ptr_factory_.GetWeakPtr());

    // Continue any pending requests.
    if (!pending_requests_.empty()) {
      for (const auto& request : pending_requests_)
        request->Run(this);
      pending_requests_.clear();
    }
  }

  // InterceptedRequestHandler methods:
  void OnBeforeRequest(const RequestId& id,
                       network::ResourceRequest* request,
                       bool request_was_redirected,
                       OnBeforeRequestResultCallback callback,
                       CancelRequestCallback cancel_callback) override {
    CEF_REQUIRE_IOT();

    if (shutting_down_) {
      // Abort immediately.
      std::move(cancel_callback).Run(net::ERR_ABORTED);
      return;
    }

    if (!init_state_) {
      // Queue requests until we're initialized.
      pending_requests_.push_back(std::make_unique<PendingRequest>(
          id, request, request_was_redirected, std::move(callback),
          std::move(cancel_callback)));
      return;
    }

    // State may already exist for restarted requests.
    RequestState* state = GetOrCreateState(id);

    // Add standard headers, if currently unspecified.
    request->headers.SetHeaderIfMissing(
        net::HttpRequestHeaders::kAcceptLanguage,
        init_state_->accept_language_);
    request->headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
                                        init_state_->user_agent_);

    const bool is_external = IsExternalRequest(request);

    // External requests will not have a default handler.
    bool intercept_only = is_external;

    CefRefPtr<CefRequestImpl> requestPtr;
    CefRefPtr<CefResourceRequestHandler> handler =
        GetHandler(id, request, &intercept_only, requestPtr);

    CefRefPtr<CefSchemeHandlerFactory> scheme_factory =
        init_state_->resource_context_->GetSchemeHandlerFactory(request->url);
    if (scheme_factory && !requestPtr) {
      requestPtr = MakeRequest(request, id.hash(), true);
    }

    // True if there's a possibility that the client might handle the request.
    const bool maybe_intercept_request = handler || scheme_factory;
    if (!maybe_intercept_request && requestPtr)
      requestPtr = nullptr;

    // May have a handler and/or scheme factory.
    state->Reset(handler, scheme_factory, requestPtr, request_was_redirected,
                 std::move(cancel_callback));

    if (handler) {
      state->cookie_filter_ = handler->GetCookieAccessFilter(
          init_state_->browser_, init_state_->frame_, requestPtr.get());
    }

    auto exec_callback =
        base::BindOnce(std::move(callback), maybe_intercept_request,
                       is_external ? true : intercept_only);

    if (!maybe_intercept_request) {
      // Cookies will be handled by the NetworkService.
      std::move(exec_callback).Run();
      return;
    }

    MaybeLoadCookies(id, state, request, std::move(exec_callback));
  }

  void MaybeLoadCookies(const RequestId& id,
                        RequestState* state,
                        network::ResourceRequest* request,
                        base::OnceClosure callback) {
    CEF_REQUIRE_IOT();

    // We need to load/save cookies ourselves for custom-handled requests, or
    // if we're using a cookie filter.
    auto allow_cookie_callback =
        state->cookie_filter_
            ? base::BindRepeating(
                  &InterceptedRequestHandlerWrapper::AllowCookieLoad,
                  weak_ptr_factory_.GetWeakPtr(), id)
            : base::BindRepeating(
                  &InterceptedRequestHandlerWrapper::AllowCookieAlways);
    auto done_cookie_callback = base::BindOnce(
        &InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
        weak_ptr_factory_.GetWeakPtr(), id, request, std::move(callback));
    net_service::LoadCookies(init_state_->browser_context_, *request,
                             allow_cookie_callback,
                             std::move(done_cookie_callback));
  }

  static void AllowCookieAlways(const net::CanonicalCookie& cookie,
                                bool* allow) {
    *allow = true;
  }

  void AllowCookieLoad(const RequestId& id,
                       const net::CanonicalCookie& cookie,
                       bool* allow) {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled while the async callback was
      // pending.
      return;
    }

    DCHECK(state->cookie_filter_);

    CefCookie cef_cookie;
    if (net_service::MakeCefCookie(cookie, cef_cookie)) {
      *allow = state->cookie_filter_->CanSendCookie(
          init_state_->browser_, init_state_->frame_,
          state->pending_request_.get(), cef_cookie);
    }
  }

  void ContinueWithLoadedCookies(const RequestId& id,
                                 network::ResourceRequest* request,
                                 base::OnceClosure callback,
                                 int total_count,
                                 net::CookieList allowed_cookies) {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled while the async callback was
      // pending.
      return;
    }

    if (state->cookie_filter_) {
      // Also add/save cookies ourselves for default-handled network requests
      // so that we can filter them. This will be a no-op for custom-handled
      // requests.
      request->load_flags |= kLoadNoCookiesFlags;
    }

    if (!allowed_cookies.empty()) {
      const std::string& cookie_line =
          net::CanonicalCookie::BuildCookieLine(allowed_cookies);
      request->headers.SetHeader(net::HttpRequestHeaders::kCookie, cookie_line);

      state->pending_request_->SetReadOnly(false);
      state->pending_request_->SetHeaderByName(net::HttpRequestHeaders::kCookie,
                                               cookie_line, true);
      state->pending_request_->SetReadOnly(true);
    }

    std::move(callback).Run();
  }

  void ShouldInterceptRequest(
      const RequestId& id,
      network::ResourceRequest* request,
      ShouldInterceptRequestResultCallback callback) override {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled during destruction.
      return;
    }

    // Must have a handler and/or scheme factory.
    DCHECK(state->handler_ || state->scheme_factory_);
    DCHECK(state->pending_request_);

    if (state->handler_) {
      // The client may modify |pending_request_| before executing the callback.
      state->pending_request_->SetReadOnly(false);
      state->pending_request_->SetTrackChanges(true,
                                               true /* backup_on_change */);

      CefRefPtr<RequestCallbackWrapper> callbackPtr =
          new RequestCallbackWrapper(base::BindOnce(
              &InterceptedRequestHandlerWrapper::ContinueShouldInterceptRequest,
              weak_ptr_factory_.GetWeakPtr(), id, base::Unretained(request),
              std::move(callback)));

      cef_return_value_t retval = state->handler_->OnBeforeResourceLoad(
          init_state_->browser_, init_state_->frame_,
          state->pending_request_.get(), callbackPtr.get());
      if (retval != RV_CONTINUE_ASYNC) {
        // Continue or cancel the request immediately.
        callbackPtr->Continue(retval == RV_CONTINUE);
      }
    } else {
      // The scheme factory may choose to handle it.
      ContinueShouldInterceptRequest(id, request, std::move(callback), true);
    }
  }

  void ContinueShouldInterceptRequest(
      const RequestId& id,
      network::ResourceRequest* request,
      ShouldInterceptRequestResultCallback callback,
      bool allow) {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled while the async callback was
      // pending.
      return;
    }

    // Must have a handler and/or scheme factory.
    DCHECK(state->handler_ || state->scheme_factory_);
    DCHECK(state->pending_request_);

    if (state->handler_) {
      if (allow) {
        // Apply any |requestPtr| changes to |request|.
        state->pending_request_->Get(request, true /* changed_only */);
      }

      const bool redirect =
          (state->pending_request_->GetChanges() & CefRequestImpl::kChangedUrl);
      if (redirect) {
        // Revert any changes for now. We'll get them back after the redirect.
        state->pending_request_->RevertChanges();
      }

      state->pending_request_->SetReadOnly(true);
      state->pending_request_->SetTrackChanges(false);

      if (!allow) {
        // Cancel the request.
        if (state->cancel_callback_) {
          std::move(state->cancel_callback_).Run(net::ERR_ABORTED);
        }
        return;
      }

      if (redirect) {
        // Performing a redirect.
        std::move(callback).Run(nullptr);
        return;
      }
    }

    CefRefPtr<CefResourceHandler> resource_handler;

    if (state->handler_) {
      // Does the client want to handle the request?
      resource_handler = state->handler_->GetResourceHandler(
          init_state_->browser_, init_state_->frame_,
          state->pending_request_.get());
    }
    if (!resource_handler && state->scheme_factory_) {
      // Does the scheme factory want to handle the request?
      resource_handler = state->scheme_factory_->Create(
          init_state_->browser_, init_state_->frame_, request->url.scheme(),
          state->pending_request_.get());
    }

    std::unique_ptr<ResourceResponse> resource_response;
    if (resource_handler) {
      resource_response = CreateResourceResponse(id, resource_handler);
      DCHECK(resource_response);
      state->was_custom_handled_ = true;
    } else {
      // The request will be handled by the NetworkService. Remove the
      // "Accept-Language" header here so that it can be re-added in
      // URLRequestHttpJob::AddExtraHeaders with correct ordering applied.
      request->headers.RemoveHeader(net::HttpRequestHeaders::kAcceptLanguage);
    }

    // Continue the request.
    std::move(callback).Run(std::move(resource_response));
  }

  void ProcessResponseHeaders(const RequestId& id,
                              const network::ResourceRequest& request,
                              const GURL& redirect_url,
                              net::HttpResponseHeaders* headers) override {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled during destruction.
      return;
    }

    if (!state->handler_)
      return;

    if (!state->pending_response_)
      state->pending_response_ = new CefResponseImpl();
    else
      state->pending_response_->SetReadOnly(false);

    if (headers)
      state->pending_response_->SetResponseHeaders(*headers);

    state->pending_response_->SetReadOnly(true);
  }

  void OnRequestResponse(const RequestId& id,
                         network::ResourceRequest* request,
                         net::HttpResponseHeaders* headers,
                         base::Optional<net::RedirectInfo> redirect_info,
                         OnRequestResponseResultCallback callback) override {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled during destruction.
      return;
    }

    if (state->cookie_filter_) {
      // Remove the flags that were added in ContinueWithLoadedCookies.
      request->load_flags &= ~kLoadNoCookiesFlags;
    }

    if (!state->handler_) {
      // Cookies may come from a scheme handler.
      MaybeSaveCookies(
          id, state, request, headers,
          base::BindOnce(
              std::move(callback), ResponseMode::CONTINUE, nullptr,
              redirect_info.has_value() ? redirect_info->new_url : GURL()));
      return;
    }

    DCHECK(state->pending_request_);
    DCHECK(state->pending_response_);

    if (redirect_info.has_value()) {
      HandleRedirect(id, state, request, headers, *redirect_info,
                     std::move(callback));
    } else {
      HandleResponse(id, state, request, headers, std::move(callback));
    }
  }

  void HandleRedirect(const RequestId& id,
                      RequestState* state,
                      network::ResourceRequest* request,
                      net::HttpResponseHeaders* headers,
                      const net::RedirectInfo& redirect_info,
                      OnRequestResponseResultCallback callback) {
    GURL new_url = redirect_info.new_url;
    CefString newUrl = redirect_info.new_url.spec();
    CefString oldUrl = newUrl;
    bool url_changed = false;
    state->handler_->OnResourceRedirect(
        init_state_->browser_, init_state_->frame_,
        state->pending_request_.get(), state->pending_response_.get(), newUrl);
    if (newUrl != oldUrl) {
      // Also support relative URLs.
      const GURL& url = redirect_info.new_url.Resolve(newUrl.ToString());
      if (url.is_valid()) {
        url_changed = true;
        new_url = url;
      }
    }

    // Update the |pending_request_| object with the new info.
    state->pending_request_->SetReadOnly(false);
    state->pending_request_->Set(redirect_info);
    if (url_changed) {
      state->pending_request_->SetURL(new_url.spec());
    }
    state->pending_request_->SetReadOnly(true);

    auto exec_callback = base::BindOnce(
        std::move(callback), ResponseMode::CONTINUE, nullptr, new_url);

    MaybeSaveCookies(id, state, request, headers, std::move(exec_callback));
  }

  void HandleResponse(const RequestId& id,
                      RequestState* state,
                      network::ResourceRequest* request,
                      net::HttpResponseHeaders* headers,
                      OnRequestResponseResultCallback callback) {
    // The client may modify |pending_request_| in OnResourceResponse.
    state->pending_request_->SetReadOnly(false);
    state->pending_request_->SetTrackChanges(true, true /* backup_on_change */);

    auto response_mode = ResponseMode::CONTINUE;
    GURL new_url;

    if (state->handler_->OnResourceResponse(
            init_state_->browser_, init_state_->frame_,
            state->pending_request_.get(), state->pending_response_.get())) {
      // The request may have been modified.
      const auto changes = state->pending_request_->GetChanges();
      if (changes) {
        state->pending_request_->Get(request, true /* changed_only */);

        if (changes & CefRequestImpl::kChangedUrl) {
          // Redirect to the new URL.
          new_url = GURL(state->pending_request_->GetURL().ToString());
        } else {
          // Restart the request.
          response_mode = ResponseMode::RESTART;
        }
      }
    }

    // Revert any changes for now. We'll get them back after the redirect or
    // restart.
    state->pending_request_->RevertChanges();

    state->pending_request_->SetReadOnly(true);
    state->pending_request_->SetTrackChanges(false);

    auto exec_callback =
        base::BindOnce(std::move(callback), response_mode, nullptr, new_url);

    if (response_mode == ResponseMode::RESTART) {
      // Get any cookies after the restart.
      std::move(exec_callback).Run();
      return;
    }

    MaybeSaveCookies(id, state, request, headers, std::move(exec_callback));
  }

  void MaybeSaveCookies(const RequestId& id,
                        RequestState* state,
                        network::ResourceRequest* request,
                        net::HttpResponseHeaders* headers,
                        base::OnceClosure callback) {
    CEF_REQUIRE_IOT();

    if (!state->cookie_filter_ && !state->was_custom_handled_) {
      // The NetworkService saves the cookies for default-handled requests.
      std::move(callback).Run();
      return;
    }

    // We need to load/save cookies ourselves for custom-handled requests, or
    // if we're using a cookie filter.
    auto allow_cookie_callback =
        state->cookie_filter_
            ? base::BindRepeating(
                  &InterceptedRequestHandlerWrapper::AllowCookieSave,
                  weak_ptr_factory_.GetWeakPtr(), id)
            : base::BindRepeating(
                  &InterceptedRequestHandlerWrapper::AllowCookieAlways);
    auto done_cookie_callback = base::BindOnce(
        &InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
        weak_ptr_factory_.GetWeakPtr(), id, std::move(callback));
    net_service::SaveCookies(init_state_->browser_context_, *request, headers,
                             allow_cookie_callback,
                             std::move(done_cookie_callback));
  }

  void AllowCookieSave(const RequestId& id,
                       const net::CanonicalCookie& cookie,
                       bool* allow) {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled while the async callback was
      // pending.
      return;
    }

    DCHECK(state->cookie_filter_);

    CefCookie cef_cookie;
    if (net_service::MakeCefCookie(cookie, cef_cookie)) {
      *allow = state->cookie_filter_->CanSaveCookie(
          init_state_->browser_, init_state_->frame_,
          state->pending_request_.get(), state->pending_response_.get(),
          cef_cookie);
    }
  }

  void ContinueWithSavedCookies(const RequestId& id,
                                base::OnceClosure callback,
                                int total_count,
                                net::CookieList allowed_cookies) {
    CEF_REQUIRE_IOT();
    std::move(callback).Run();
  }

  mojo::ScopedDataPipeConsumerHandle OnFilterResponseBody(
      const RequestId& id,
      const network::ResourceRequest& request,
      mojo::ScopedDataPipeConsumerHandle body) override {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled during destruction.
      return body;
    }

    if (state->handler_) {
      auto filter = state->handler_->GetResourceResponseFilter(
          init_state_->browser_, init_state_->frame_,
          state->pending_request_.get(), state->pending_response_.get());
      if (filter) {
        return CreateResponseFilterHandler(
            filter, std::move(body),
            base::BindOnce(&InterceptedRequestHandlerWrapper::OnFilterError,
                           weak_ptr_factory_.GetWeakPtr(), id));
      }
    }

    return body;
  }

  void OnFilterError(const RequestId& id) {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been canceled while the async callback was
      // pending.
      return;
    }

    if (state->cancel_callback_) {
      std::move(state->cancel_callback_).Run(net::ERR_CONTENT_DECODING_FAILED);
    }
  }

  void OnRequestComplete(
      const RequestId& id,
      const network::ResourceRequest& request,
      const network::URLLoaderCompletionStatus& status) override {
    CEF_REQUIRE_IOT();

    RequestState* state = GetState(id);
    if (!state) {
      // The request may have been aborted during initialization or canceled
      // during destruction. This method will always be called before a request
      // is deleted, so if the request is currently pending also remove it from
      // the list.
      if (!pending_requests_.empty()) {
        PendingRequests::iterator it = pending_requests_.begin();
        for (; it != pending_requests_.end(); ++it) {
          if ((*it)->id_ == id) {
            pending_requests_.erase(it);
            break;
          }
        }
      }
      return;
    }

    const bool is_external = IsExternalRequest(&request);

    // Redirection of standard custom schemes is handled with a restart, so we
    // get completion notifications for both the original (redirected) request
    // and the final request. Don't report completion of the redirected request.
    const bool ignore_result = is_external && request.url.IsStandard() &&
                               status.error_code == net::ERR_ABORTED &&
                               state->pending_response_.get() &&
                               net::HttpResponseHeaders::IsRedirectResponseCode(
                                   state->pending_response_->GetStatus());

    if (state->handler_ && !ignore_result) {
      DCHECK(state->pending_request_);

      CallHandlerOnComplete(state, status);

      if (status.error_code != 0 && is_external) {
        bool allow_os_execution = false;
        state->handler_->OnProtocolExecution(
            init_state_->browser_, init_state_->frame_,
            state->pending_request_.get(), allow_os_execution);
        if (allow_os_execution) {
          CefBrowserPlatformDelegate::HandleExternalProtocol(request.url);
        }
      }
    }

    RemoveState(id);
  }

 private:
  void CallHandlerOnComplete(RequestState* state,
                             const network::URLLoaderCompletionStatus& status) {
    if (!state->handler_ || !state->pending_request_)
      return;

    // The request object may be currently flagged as writable in cases where we
    // abort a request that is waiting on a pending callack.
    if (!state->pending_request_->IsReadOnly()) {
      state->pending_request_->SetReadOnly(true);
    }

    if (!state->pending_response_) {
      // If the request failed there may not be a response object yet.
      state->pending_response_ = new CefResponseImpl();
    } else {
      state->pending_response_->SetReadOnly(false);
    }
    state->pending_response_->SetError(
        static_cast<cef_errorcode_t>(status.error_code));
    state->pending_response_->SetReadOnly(true);

    state->handler_->OnResourceLoadComplete(
        init_state_->browser_, init_state_->frame_,
        state->pending_request_.get(), state->pending_response_.get(),
        status.error_code == 0 ? UR_SUCCESS : UR_FAILED,
        status.encoded_body_length);
  }

  // Returns the handler, if any, that should be used for this request.
  CefRefPtr<CefResourceRequestHandler> GetHandler(
      const RequestId& id,
      network::ResourceRequest* request,
      bool* intercept_only,
      CefRefPtr<CefRequestImpl>& requestPtr) const {
    CefRefPtr<CefResourceRequestHandler> handler;

    const int64 request_id = id.hash();

    if (init_state_->browser_) {
      // Maybe the browser's client wants to handle it?
      CefRefPtr<CefClient> client =
          init_state_->browser_->GetHost()->GetClient();
      if (client) {
        CefRefPtr<CefRequestHandler> request_handler =
            client->GetRequestHandler();
        if (request_handler) {
          requestPtr = MakeRequest(request, request_id, true);

          handler = request_handler->GetResourceRequestHandler(
              init_state_->browser_, init_state_->frame_, requestPtr.get(),
              init_state_->is_navigation_, init_state_->is_download_,
              init_state_->request_initiator_, *intercept_only);
        }
      }
    }

    if (!handler) {
      // Maybe the request context wants to handle it?
      CefRefPtr<CefRequestContextHandler> context_handler =
          init_state_->resource_context_->GetHandler(
              init_state_->render_process_id_, request->render_frame_id,
              init_state_->frame_tree_node_id_, false);
      if (context_handler) {
        if (!requestPtr)
          requestPtr = MakeRequest(request, request_id, true);

        handler = context_handler->GetResourceRequestHandler(
            init_state_->browser_, init_state_->frame_, requestPtr.get(),
            init_state_->is_navigation_, init_state_->is_download_,
            init_state_->request_initiator_, *intercept_only);
      }
    }

    return handler;
  }

  RequestState* GetOrCreateState(const RequestId& id) {
    RequestState* state = GetState(id);
    if (!state) {
      state = new RequestState();
      request_map_.insert(std::make_pair(id, base::WrapUnique(state)));
    }
    return state;
  }

  RequestState* GetState(const RequestId& id) const {
    RequestMap::const_iterator it = request_map_.find(id);
    if (it != request_map_.end())
      return it->second.get();
    return nullptr;
  }

  void RemoveState(const RequestId& id) {
    RequestMap::iterator it = request_map_.find(id);
    DCHECK(it != request_map_.end());
    if (it != request_map_.end())
      request_map_.erase(it);
  }

  // Stop accepting new requests and cancel pending/in-flight requests when the
  // CEF context or associated browser is destroyed.
  void OnDestroyed() {
    CEF_REQUIRE_IOT();
    DCHECK(init_state_);

    init_state_->DeleteDestructionObserver();

    // Stop accepting new requests.
    shutting_down_ = true;

    // Stop the delivery of pending callbacks.
    weak_ptr_factory_.InvalidateWeakPtrs();

    // Take ownership of any pending requests.
    PendingRequests pending_requests;
    pending_requests.swap(pending_requests_);

    // Take ownership of any in-progress requests.
    RequestMap request_map;
    request_map.swap(request_map_);

    // Notify handlers for in-progress requests.
    for (const auto& pair : request_map) {
      CallHandlerOnComplete(
          pair.second.get(),
          network::URLLoaderCompletionStatus(net::ERR_ABORTED));
    }

    if (init_state_->browser_) {
      // Clear objects that reference the browser.
      init_state_->browser_ = nullptr;
      init_state_->frame_ = nullptr;
    }

    // Execute cancel callbacks and delete pending and in-progress requests.
    // This may result in the request being torn down sooner, or it may be
    // ignored if the request is already in the process of being torn down. When
    // the last callback is executed it may result in |this| being deleted.
    pending_requests.clear();

    for (auto& pair : request_map) {
      auto state = std::move(pair.second);
      if (state->cancel_callback_) {
        std::move(state->cancel_callback_).Run(net::ERR_ABORTED);
      }
    }
  }

  static CefRefPtr<CefRequestImpl> MakeRequest(
      const network::ResourceRequest* request,
      int64 request_id,
      bool read_only) {
    CefRefPtr<CefRequestImpl> requestPtr = new CefRequestImpl();
    requestPtr->Set(request, request_id);
    if (read_only)
      requestPtr->SetReadOnly(true);
    else
      requestPtr->SetTrackChanges(true);
    return requestPtr;
  }

  // Returns true if |request| cannot be handled internally.
  static bool IsExternalRequest(const network::ResourceRequest* request) {
    return !scheme::IsInternalHandledScheme(request->url.scheme());
  }

  scoped_refptr<InitHelper> init_helper_;
  std::unique_ptr<InitState> init_state_;

  bool shutting_down_ = false;

  using RequestMap = std::map<RequestId, std::unique_ptr<RequestState>>;
  RequestMap request_map_;

  using PendingRequests = std::vector<std::unique_ptr<PendingRequest>>;
  PendingRequests pending_requests_;

  base::WeakPtrFactory<InterceptedRequestHandlerWrapper> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(InterceptedRequestHandlerWrapper);
};

void InitOnUIThread(
    scoped_refptr<InterceptedRequestHandlerWrapper::InitHelper> init_helper,
    content::WebContents::Getter web_contents_getter,
    int frame_tree_node_id,
    const network::ResourceRequest& request) {
  CEF_REQUIRE_UIT();

  // May return nullptr if the WebContents was destroyed while this callback was
  // in-flight.
  content::WebContents* web_contents = web_contents_getter.Run();
  if (!web_contents) {
    return;
  }

  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
  DCHECK(browser_context);

  const int render_process_id =
      web_contents->GetRenderViewHost()->GetProcess()->GetID();

  content::RenderFrameHost* frame = nullptr;

  if (request.render_frame_id >= 0) {
    // TODO(network): Are these main frame checks equivalent?
    if (request.is_main_frame ||
        static_cast<blink::mojom::ResourceType>(request.resource_type) ==
            blink::mojom::ResourceType::kMainFrame) {
      frame = web_contents->GetMainFrame();
      DCHECK(frame);
    } else {
      // May return null for newly created iframes.
      frame = content::RenderFrameHost::FromID(render_process_id,
                                               request.render_frame_id);
      if (!frame && frame_tree_node_id >= 0) {
        // May return null for frames in inner WebContents.
        frame = web_contents->FindFrameByFrameTreeNodeId(frame_tree_node_id,
                                                         render_process_id);
      }
      if (!frame) {
        // Use the main frame for the CefBrowserHost.
        frame = web_contents->GetMainFrame();
        DCHECK(frame);
      }
    }
  }

  CefRefPtr<CefBrowserHostImpl> browserPtr;
  CefRefPtr<CefFrame> framePtr;

  // |frame| may be null for service worker requests.
  if (frame) {
    // May return nullptr for requests originating from guest views.
    browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
    if (browserPtr) {
      framePtr = browserPtr->GetFrameForHost(frame);
      if (frame_tree_node_id < 0)
        frame_tree_node_id = frame->GetFrameTreeNodeId();
      DCHECK(framePtr);
    }
  }

  const bool is_navigation = ui::PageTransitionIsNewNavigation(
      static_cast<ui::PageTransition>(request.transition_type));
  // TODO(navigation): Can we determine the |is_download| value?
  const bool is_download = false;
  url::Origin request_initiator;
  if (request.request_initiator.has_value())
    request_initiator = *request.request_initiator;

  auto init_state =
      std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
  init_state->Initialize(browser_context, browserPtr, framePtr,
                         render_process_id, request.render_frame_id,
                         frame_tree_node_id, is_navigation, is_download,
                         request_initiator);

  init_helper->MaybeSetInitialized(std::move(init_state));
}

}  // namespace

std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
    content::BrowserContext* browser_context,
    content::RenderFrameHost* frame,
    int render_process_id,
    bool is_navigation,
    bool is_download,
    const url::Origin& request_initiator) {
  CEF_REQUIRE_UIT();
  CefRefPtr<CefBrowserHostImpl> browserPtr;
  CefRefPtr<CefFrame> framePtr;
  int render_frame_id = -1;
  int frame_tree_node_id = -1;

  // |frame| may be null for service worker requests.
  if (frame) {
    render_frame_id = frame->GetRoutingID();
    frame_tree_node_id = frame->GetFrameTreeNodeId();

    // May return nullptr for requests originating from guest views.
    browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame);
    if (browserPtr) {
      framePtr = browserPtr->GetFrameForHost(frame);
      DCHECK(framePtr);
    }
  }

  auto init_state =
      std::make_unique<InterceptedRequestHandlerWrapper::InitState>();
  init_state->Initialize(browser_context, browserPtr, framePtr,
                         render_process_id, render_frame_id, frame_tree_node_id,
                         is_navigation, is_download, request_initiator);

  auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
  wrapper->init_helper()->MaybeSetInitialized(std::move(init_state));

  return wrapper;
}

std::unique_ptr<InterceptedRequestHandler> CreateInterceptedRequestHandler(
    content::WebContents::Getter web_contents_getter,
    int frame_tree_node_id,
    const network::ResourceRequest& request) {
  auto wrapper = std::make_unique<InterceptedRequestHandlerWrapper>();
  CEF_POST_TASK(CEF_UIT, base::BindOnce(InitOnUIThread, wrapper->init_helper(),
                                        web_contents_getter, frame_tree_node_id,
                                        request));
  return wrapper;
}

}  // namespace net_service
