CEF:为“file://”请求重定向或创建新的“CefResourceHandler”以改用“https://”

CEF: redirect or create new `CefResourceHandler` for `file://` request to use `https://' instead

CEF 在我的本地应用程序中将所有协议相关 URL 视为 file:// 请求,我想拦截并将其更改为指向 https://

我重载了以下来自 CefRequestHandler 的两个方法:

  virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request);

  virtual cef_return_value_t OnBeforeResourceLoad(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request,
      CefRefPtr<CefRequestCallback> callback);

其中 cef_return_value_t 定义为:

typedef enum {
  ///
  // Cancel immediately.
  ///
  RV_CANCEL = 0,
  ///
  // Continue immediately.
  ///
  RV_CONTINUE,
  ///
  // Continue asynchronously (usually via a callback).
  ///
  RV_CONTINUE_ASYNC,
} cef_return_value_t;

OnBeforeResourceLoad,我只能要求CEF取消或继续申请。所以,我要返回 RV_CONTINUE

而在 GetResourceHandler 中,我可以提供自定义 CefResourceHandler

但问题是,我找不到 CEF api 来帮助我创建自己的 https:// 请求处理程序。

在文件cef/tests/ceftests/navigation_unittest.cc中,class后面的文件可以作为实现RedirectRequestHandler的参考。您需要修改内部结构,可以使用 http:302redirectUrl 中的任何一个来实现重定向。

class RedirectSchemeHandler : public CefResourceHandler {
 public:
  RedirectSchemeHandler() : offset_(0), status_(0) {}

  bool ProcessRequest(CefRefPtr<CefRequest> request,
                      CefRefPtr<CefCallback> callback) override {
    EXPECT_TRUE(CefCurrentlyOn(TID_IO));

    std::string url = request->GetURL();
    if (url == kRNav1) {
      // Redirect using HTTP 302
      g_got_nav1_request = true;
      status_ = 302;
      location_ = kRNav2;
      content_ = "<html><body>Redirected Nav1</body></html>";
    } else if (url == kRNav3) {
      // Redirect using redirectUrl
      g_got_nav3_request = true;
      status_ = -1;
      location_ = kRNav4;
      content_ = "<html><body>Redirected Nav3</body></html>";
    } else if (url == kRNav4) {
      g_got_nav4_request = true;
      status_ = 200;
      content_ = "<html><body>Nav4</body></html>";
    }

    if (status_ != 0) {
      callback->Continue();
      return true;
    } else {
      g_got_invalid_request = true;
      return false;
    }
  }

  void GetResponseHeaders(CefRefPtr<CefResponse> response,
                          int64& response_length,
                          CefString& redirectUrl) override {
    EXPECT_TRUE(CefCurrentlyOn(TID_IO));

    EXPECT_NE(status_, 0);

    response->SetStatus(status_);
    response->SetMimeType("text/html");
    response_length = content_.size();

    if (status_ == 302) {
      // Redirect using HTTP 302
      EXPECT_GT(location_.size(), static_cast<size_t>(0));
      response->SetStatusText("Found");
      CefResponse::HeaderMap headers;
      response->GetHeaderMap(headers);
      headers.insert(std::make_pair("Location", location_));
      response->SetHeaderMap(headers);
    } else if (status_ == -1) {
      // Rdirect using redirectUrl
      EXPECT_GT(location_.size(), static_cast<size_t>(0));
      redirectUrl = location_;
    }
  }

  void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }

  bool ReadResponse(void* data_out,
                    int bytes_to_read,
                    int& bytes_read,
                    CefRefPtr<CefCallback> callback) override {
    EXPECT_TRUE(CefCurrentlyOn(TID_IO));

    size_t size = content_.size();
    if (offset_ < size) {
      int transfer_size =
          std::min(bytes_to_read, static_cast<int>(size - offset_));
      memcpy(data_out, content_.c_str() + offset_, transfer_size);
      offset_ += transfer_size;

      bytes_read = transfer_size;
      return true;
    }

    return false;
  }

 protected:
  std::string content_;
  size_t offset_;
  int status_;
  std::string location_;

  IMPLEMENT_REFCOUNTING(RedirectSchemeHandler);
};

RedirectSchemeHandler 的实例应该从以下 callback:

返回
virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
          CefRefPtr<CefBrowser> browser,
          CefRefPtr<CefFrame> frame,
          CefRefPtr<CefRequest> request)
{
      return new RedirectSchemeHandler();
}