Chromium 自定义缓存策略


Chromium Embedded Framework (CEF) 是一个开源库,用于在应用程序中嵌入 Chromium web 浏览器控制。CEF 本身并没有直接提供自定义缓存策略的接口。它主要遵循 Chromium 的缓存策略。
然而,你可以通过一些方式间接地实现自定义缓存策略:

  1. 自定义请求处理:你可以通过实现 CefRequestHandler 接口来自定义请求的处理。例如,你可以在 OnBeforeResourceLoad 方法中修改请求的头部,添加或修改 Cache-Control 头部来控制缓存行为。
  2. 禁用缓存:如果你想完全禁用缓存,你可以在创建 CefBrowser 或 CefRequest 时设置 cache_path 为空。
  3. 离线缓存:CEF 支持 HTML5 的应用程序缓存(AppCache),你可以使用它来实现离线缓存。
  4. 自定义协议:你可以通过实现 CefSchemeHandlerFactory 和 CefResourceHandler 来创建自定义协议,然后在自定义协议中实现你自己的缓存策略。
    请注意,以上方法可能需要对 CEF 和 Chromium 的内部机制有一定的了解,并且可能需要一些编程工作。

CefRequestHandler 在什么位置实现

CefRequestHandler是一个接口,你可以通过创建一个新的类来实现它,这个新类可以在你的项目中的任何位置。以下是一个基本的例子:

class MyRequestHandler : public CefRequestHandler {
public:    MyRequestHandler() {}    
virtual ~MyRequestHandler() {}    
// Implement methods from CefRequestHandler as needed.    
// For example:    
virtual ReturnValue OnBeforeResourceLoad(        
CefRefPtr browser,        
CefRefPtr frame,        
CefRefPtr request,        
CefRefPtr callback) OVERRIDE {        
// Modify request as needed.        
return RV_CONTINUE;   
}
private:    
IMPLEMENT_REFCOUNTING(MyRequestHandler);};

然后你需要在你的CefClient实现中返回这个处理器:

class MyClient : public CefClient {
public:    MyClient() : request_handler_(new MyRequestHandler()) {}   
virtual CefRefPtr GetRequestHandler() OVERRIDE {       
return request_handler_;    
}    
// Implement other methods as needed.
private:    
CefRefPtr request_handler_;    
IMPLEMENT_REFCOUNTING(MyClient);};

这样,CEF 就会在适当的时候调用你的MyRequestHandler实现。

我如何将本地资源作为该请求资源返回呢?

在CEF(Chromium Embedded Framework)中,你可以通过实现自定义的CefResourceHandler来实现这个功能。下面是一个简单的例子:

class MyResourceHandler : public CefResourceHandler {
public:
    MyResourceHandler() {}

    bool ProcessRequest(CefRefPtr<CefRequest> request,
                        CefRefPtr<CefCallback> callback) OVERRIDE {
        // Check the URL of the request and decide whether you want to handle this request.
        if (request->GetURL() == "http://my.custom.url") {
            // Use callback->Continue() to start the request.
            callback->Continue();
            return true;
        }
        return false;
    }

    void GetResponseHeaders(CefRefPtr<CefResponse> response,
                            int64& response_length,
                            CefString& redirectUrl) OVERRIDE {
        // Set up the response headers.
        response->SetMimeType("text/html");
        response->SetStatus(200);

        // Load the resource from local storage.
        std::string html_content = "<html><body>Hello, world!</body></html>";
        data_ = html_content;
        response_length = data_.size();
    }

    bool ReadResponse(void* data_out,
                      int bytes_to_read,
                      int& bytes_read,
                      CefRefPtr<CefCallback> callback) OVERRIDE {
        // Copy the data from your local resource to data_out.
        int size = std::min(bytes_to_read, static_cast<int>(data_.size()));
        memcpy(data_out, data_.c_str(), size);
        bytes_read = size;
        data_ = data_.substr(size);
        return true;
    }

private:
    std::string data_;

    IMPLEMENT_REFCOUNTING(MyResourceHandler);
};

然后在你的CefRequestHandler实现中返回这个资源处理器:

lass MyRequestHandler : public CefRequestHandler {
public:
    MyRequestHandler() {}

    CefRefPtr<CefResourceHandler> GetResourceHandler(
        CefRefPtr<CefBrowser> browser,
        CefRefPtr<CefFrame> frame,
        CefRefPtr<CefRequest> request) OVERRIDE {
        return new MyResourceHandler();
    }

    // Implement other methods as needed.

private:
    IMPLEMENT_REFCOUNTING(MyRequestHandler);
};

这样,当请求的URL匹配你的自定义URL时,CEF会调用你的MyResourceHandler来处理这个请求,并从本地资源中读取数据。

我怎么缓存网络资源呢,比如图片和视频?

CEF(Chromium Embedded Framework)本身已经包含了一个强大的缓存机制,它会自动缓存网络请求的结果(包括图片和视频)。你只需要在创建CefSettings时,设置cache_path属性为你想要的缓存路径即可:

CefSettings settings;
CefString(&settings.cache_path) = "/path/to/cache";

这样CEF就会自动将网络资源缓存在指定的路径下。

如果你想要更细粒度的控制,比如只缓存特定的资源,或者自定义缓存的策略,你可能需要实现自己的CefResourceHandler,在其中处理资源的缓存。这需要对CEF的内部机制有深入的理解,且可能需要大量的代码来实现。

CefResourceHandler 如何实现缓存图片和视频,缓存时间无限长,设置缓存路径?

CEF(Chromium Embedded Framework)并没有直接提供在CefResourceHandler中设置无限长缓存时间和缓存路径的API。缓存是由CEF内部的网络堆栈自动处理的,而CefResourceHandler主要用于处理自定义的资源请求。

如果你想要控制资源的缓存,你可能需要实现自己的缓存机制。这通常涉及到以下步骤:

在CefResourceHandler的ProcessRequest方法中,检查请求的URL,看是否是你想要缓存的资源。

如果是,那么检查你的缓存(你需要自己实现缓存的存储和检索),看是否已经缓存了这个资源。

如果已经缓存了这个资源,那么在GetResponseHeaders和ReadResponse方法中,返回缓存的资源。

如果没有缓存这个资源,那么继续处理请求,将请求的结果保存到你的缓存中。

这个过程需要你自己实现缓存的存储和检索,包括缓存的路径和过期时间。你可以使用任何你喜欢的存储机制,比如文件系统、数据库等。你也需要自己处理缓存的过期,比如在每次检索缓存时,检查缓存的时间,如果超过你设定的过期时间,那么删除这个缓存。

请注意,这是一个复杂的过程,需要对CEF和网络编程有深入的理解。并且,由于CEF的网络堆栈已经提供了强大的缓存机制,所以在大多数情况下,你可能并不需要自己实现这个功能。

demo

下是一个基本的 CefResourceHandler 的实现示例。这只是一个基础模板,并没有实现缓存功能。要实现缓存功能,你需要在适当的位置添加额外的代码来处理缓存的存储和检索。

class MyResourceHandler : public CefResourceHandler {
 public:
  MyResourceHandler() : offset_(0) {}

  bool ProcessRequest(CefRefPtr<CefRequest> request,
                      CefRefPtr<CefCallback> callback) OVERRIDE {
    REQUIRE_IO_THREAD();

    // TODO: 在这里检查请求的URL,看是否是你想要缓存的资源。

    // TODO: 如果是,检查你的缓存,看是否已经缓存了这个资源。

    // TODO: 如果已经缓存了这个资源,调用callback->Continue()然后返回true。

    // TODO: 如果没有缓存这个资源,继续处理请求。

    return false;
  }

  void GetResponseHeaders(CefRefPtr<CefResponse> response,
                          int64& response_length,
                          CefString& redirectUrl) OVERRIDE {
    REQUIRE_IO_THREAD();

    // TODO: 如果是从缓存中获取的资源,设置相应的响应头。

    // TODO: 设置response_length为资源的长度。
  }

  bool ReadResponse(void* data_out,
                    int bytes_to_read,
                    int& bytes_read,
                    CefRefPtr<CefCallback> callback) OVERRIDE {
    REQUIRE_IO_THREAD();

    // TODO: 如果是从缓存中获取的资源,读取资源到data_out,并设置bytes_read。

    return false;
  }

  bool CanGetCookie(const CefCookie& cookie) OVERRIDE {
    REQUIRE_IO_THREAD();

    // Allow all cookies.
    return true;
  }

  bool CanSetCookie(const CefCookie& cookie) OVERRIDE {
    REQUIRE_IO_THREAD();

    // Allow all cookies.
    return true;
  }

  void Cancel() OVERRIDE {
    REQUIRE_IO_THREAD();
  }

 private:
  std::string data_;
  size_t offset_;

  IMPLEMENT_REFCOUNTING(MyResourceHandler);
};

这个示例中,你需要在 ProcessRequest 方法中检查请求的 URL 和你的缓存,然后在 GetResponseHeaders 和 ReadResponse 方法中返回缓存的资源。你还需要在适当的位置处理缓存的存储和过期。

请注意,这个示例只是一个基础模板,实际的实现可能会更复杂。你可能需要处理各种网络错误,以及缓存的并发访问等问题。你还需要确保你的实现符合HTTP的缓存规则,比如考虑到 Cache-Control 和 Expires 等HTTP头。

MyResourceHandler 在哪里设置?

在CEF中,CefResourceHandler 通常在 CefRequestHandler 的 GetResourceHandler 方法中设置。你需要创建一个实现了 CefRequestHandler 的类,并在 GetResourceHandler 方法中返回你的 MyResourceHandler 实例。

以下是一个基本的示例:

class MyRequestHandler : public CefRequestHandler {
 public:
  MyRequestHandler() {}

  CefRefPtr<CefResourceHandler> GetResourceHandler(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request) OVERRIDE {
    REQUIRE_IO_THREAD();

    // TODO: 在这里检查请求的URL,看是否是你想要处理的资源。

    // TODO: 如果是,创建一个MyResourceHandler实例,并返回。

    return NULL;
  }

  IMPLEMENT_REFCOUNTING(MyRequestHandler);
};

然后,你需要在创建 CefBrowser 时设置这个 CefRequestHandler。这通常在 CefBrowserHost::CreateBrowser 或 CefBrowserHost::CreateBrowserSync 调用时完成。例如:

CefWindowInfo window_info;
CefBrowserSettings browser_settings;
CefRefPtr<MyRequestHandler> request_handler = new MyRequestHandler();

// 创建一个新的CefBrowser实例。
CefBrowserHost::CreateBrowser(window_info, request_handler, url, browser_settings, NULL);

在这个示例中,CEF会在处理每个请求时调用 MyRequestHandler::GetResourceHandler 方法。如果这个方法返回一个 CefResourceHandler 实例,那么CEF将使用这个handler来处理请求。否则,CEF将使用默认的网络堆栈来处理请求。

posted @ 2024-04-08 11:34  严_青  阅读(260)  评论(0编辑  收藏  举报