<commit_before>// Copyright (c) 2012 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/url_network_delegate.h"

#include <string>

#include "include/cef_urlrequest.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/url_request_user_data.h"
#include "libcef/common/request_impl.h"

#include "net/base/net_errors.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"

namespace {

class CefBeforeResourceLoadCallbackImpl : public CefRequestCallback {
 public:
  typedef net::CompletionCallback CallbackType;

  CefBeforeResourceLoadCallbackImpl(
      CefRefPtr<CefRequestImpl> cef_request,
      GURL* new_url,
      net::URLRequest* url_request,
      const CallbackType& callback)
      : cef_request_(cef_request),
        new_url_(new_url),
        url_request_(url_request),
        callback_(callback) {
    DCHECK(new_url);
    DCHECK(url_request_);

    // Add an association between the URLRequest and this object.
    url_request_->SetUserData(UserDataKey(), new Disconnector(this));
  }

  ~CefBeforeResourceLoadCallbackImpl() {
    if (!callback_.is_null()) {
      // The callback is still pending. Cancel it now.
      if (CEF_CURRENTLY_ON_IOT()) {
        RunNow(cef_request_, new_url_, url_request_, callback_, false);
      } else {
        CEF_POST_TASK(CEF_IOT,
            base::Bind(&CefBeforeResourceLoadCallbackImpl::RunNow,
                       cef_request_, new_url_, url_request_, callback_, false));
      }
    }
  }

  void Continue(bool allow) override {
    // Always continue asynchronously.
    CEF_POST_TASK(CEF_IOT,
        base::Bind(&CefBeforeResourceLoadCallbackImpl::ContinueNow,
                   this, allow));
  }

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

  void ContinueNow(bool allow) {
    CEF_REQUIRE_IOT();
    if (!callback_.is_null()) {
      RunNow(cef_request_, new_url_, url_request_, callback_, allow);
      Disconnect();
    }
  }

  void Disconnect() {
    CEF_REQUIRE_IOT();
    cef_request_ = nullptr;
    new_url_ = nullptr;
    url_request_ = nullptr;
    callback_.Reset();
  }

 private:
  // Used to disconnect the callback when the associated URLRequest is
  // destroyed.
  class Disconnector : public base::SupportsUserData::Data {
   public:
    explicit Disconnector(CefBeforeResourceLoadCallbackImpl* callback)
        : callback_(callback) {
    }
    ~Disconnector() override {
      if (callback_)
        callback_->Disconnect();
    }

    void Disconnect() {
      callback_ = NULL;
    }

   private:
    CefBeforeResourceLoadCallbackImpl* callback_;
  };

  static void RunNow(CefRefPtr<CefRequestImpl> cef_request,
                     GURL* new_url,
                     net::URLRequest* request,
                     const CallbackType& callback,
                     bool allow) {
    CEF_REQUIRE_IOT();

    if (allow) {
      const GURL& old_url = request->url();
      GURL url = GURL(cef_request->GetURL().ToString());
      if (old_url != url)
        new_url->Swap(&url);

      cef_request->Get(request);
    }

    // Remove the association between the URLRequest and this object.
    Disconnector* disconnector =
        static_cast<Disconnector*>(request->GetUserData(UserDataKey()));
    DCHECK(disconnector);
    disconnector->Disconnect();
    request->RemoveUserData(UserDataKey());

    callback.Run(allow ? net::OK : net::ERR_ABORTED);
  }

  static inline void* UserDataKey() {
    return &kLocatorKey;
  }

  CefRefPtr<CefRequestImpl> cef_request_;
  const GURL old_url_;<commit_msg>Don't execute URLRequest callback for already canceled requests (issue #1685)<commit_after>// Copyright (c) 2012 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/url_network_delegate.h"

#include <string>

#include "include/cef_urlrequest.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/url_request_user_data.h"
#include "libcef/common/request_impl.h"

#include "net/base/net_errors.h"
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"

namespace {

class CefBeforeResourceLoadCallbackImpl : public CefRequestCallback {
 public:
  typedef net::CompletionCallback CallbackType;

  CefBeforeResourceLoadCallbackImpl(
      CefRefPtr<CefRequestImpl> cef_request,
      GURL* new_url,
      net::URLRequest* url_request,
      const CallbackType& callback)
      : cef_request_(cef_request),
        new_url_(new_url),
        url_request_(url_request),
        callback_(callback) {
    DCHECK(new_url);
    DCHECK(url_request_);

    // Add an association between the URLRequest and this object.
    url_request_->SetUserData(UserDataKey(), new Disconnector(this));
  }

  ~CefBeforeResourceLoadCallbackImpl() {
    if (!callback_.is_null()) {
      // The callback is still pending. Cancel it now.
      if (CEF_CURRENTLY_ON_IOT()) {
        RunNow(cef_request_, new_url_, url_request_, callback_, false);
      } else {
        CEF_POST_TASK(CEF_IOT,
            base::Bind(&CefBeforeResourceLoadCallbackImpl::RunNow,
                       cef_request_, new_url_, url_request_, callback_, false));
      }
    }
  }

  void Continue(bool allow) override {
    // Always continue asynchronously.
    CEF_POST_TASK(CEF_IOT,
        base::Bind(&CefBeforeResourceLoadCallbackImpl::ContinueNow,
                   this, allow));
  }

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

  void ContinueNow(bool allow) {
    CEF_REQUIRE_IOT();
    if (!callback_.is_null()) {
      RunNow(cef_request_, new_url_, url_request_, callback_, allow);
      Disconnect();
    }
  }

  void Disconnect() {
    CEF_REQUIRE_IOT();
    cef_request_ = nullptr;
    new_url_ = nullptr;
    url_request_ = nullptr;
    callback_.Reset();
  }

 private:
  // Used to disconnect the callback when the associated URLRequest is
  // destroyed.
  class Disconnector : public base::SupportsUserData::Data {
   public:
    explicit Disconnector(CefBeforeResourceLoadCallbackImpl* callback)
        : callback_(callback) {
    }
    ~Disconnector() override {
      if (callback_)
        callback_->Disconnect();
    }

    void Disconnect() {
      callback_ = NULL;
    }

   private:
    CefBeforeResourceLoadCallbackImpl* callback_;
  };

  static void RunNow(CefRefPtr<CefRequestImpl> cef_request,
                     GURL* new_url,
                     net::URLRequest* request,
                     const CallbackType& callback,
                     bool allow) {
    CEF_REQUIRE_IOT();

    if (allow) {
      const GURL& old_url = request->url();
      GURL url = GURL(cef_request->GetURL().ToString());
      if (old_url != url)
        new_url->Swap(&url);

      cef_request->Get(request);
    }

    // Remove the association between the URLRequest and this object.
    Disconnector* disconnector =
        static_cast<Disconnector*>(request->GetUserData(UserDataKey()));
    DCHECK(disconnector);
    disconnector->Disconnect();
    request->RemoveUserData(UserDataKey());

    // Only execute the callback if the request has not been canceled.
    if (request->status().status() != net::URLRequestStatus::CANCELED)
      callback.Run(allow ? net::OK : net::ERR_ABORTED);
  }

  static inline void* UserDataKey() {
    return &kLocatorKey;
  }

  CefRefPtr<CefRequestImpl> cef_request_;
  const GURL old_url_;
{'fraction_non_alphanumeric': 0.10530441599163835, 'fraction_numerical': 0.001567807682257643, 'mean_word_length': 3.162588363240892, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4539474', 'n_tokens_mistral': 2409, 'n_tokens_neox': 2347, 'n_words': 504}