mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for response filtering (issue #515).
- Add a new CefRequestHandler::GetResourceResponseFilter method and CefResponseFilter class.
This commit is contained in:
@ -8,17 +8,23 @@
|
||||
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/net/response_filter_wrapper.h"
|
||||
#include "libcef/browser/net/url_request_user_data.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
#include "libcef/common/request_impl.h"
|
||||
#include "libcef/common/response_impl.h"
|
||||
|
||||
#include "net/base/net_errors.h"
|
||||
#include "net/filter/filter.h"
|
||||
#include "net/http/http_util.h"
|
||||
#include "net/url_request/url_request.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Buffer size allocated when filtering data.
|
||||
// Should match the value in net/filter/filter.cc.
|
||||
const int kFilterBufSize = 32 * 1024;
|
||||
|
||||
class CefBeforeResourceLoadCallbackImpl : public CefRequestCallback {
|
||||
public:
|
||||
typedef net::CompletionCallback CallbackType;
|
||||
@ -380,3 +386,55 @@ bool CefNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
|
||||
const base::FilePath& path) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
net::Filter* CefNetworkDelegate::SetupFilter(net::URLRequest* request,
|
||||
net::Filter* filter_list) {
|
||||
CefRefPtr<CefResponseFilter> cef_filter;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserForRequest(request);
|
||||
if (browser.get()) {
|
||||
CefRefPtr<CefClient> client = browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefFrame> frame = browser->GetFrameForRequest(request);
|
||||
|
||||
CefRefPtr<CefRequestImpl> cefRequest = new CefRequestImpl();
|
||||
cefRequest->Set(request);
|
||||
cefRequest->SetReadOnly(true);
|
||||
|
||||
CefRefPtr<CefResponseImpl> cefResponse = new CefResponseImpl();
|
||||
cefResponse->Set(request);
|
||||
cefResponse->SetReadOnly(true);
|
||||
|
||||
cef_filter = handler->GetResourceResponseFilter(browser.get(), frame,
|
||||
cefRequest.get(),
|
||||
cefResponse.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cef_filter.get() && cef_filter->InitFilter()) {
|
||||
scoped_ptr<CefResponseFilterWrapper> wrapper(
|
||||
new CefResponseFilterWrapper(cef_filter, filter_list != nullptr));
|
||||
wrapper->InitBuffer(kFilterBufSize);
|
||||
|
||||
if (filter_list) {
|
||||
// Install the wrapper at the end of the filter list.
|
||||
net::Filter* last_filter = filter_list;
|
||||
do {
|
||||
if (!last_filter->next_filter_.get()) {
|
||||
last_filter->next_filter_ = wrapper.Pass();
|
||||
break;
|
||||
}
|
||||
last_filter = last_filter->next_filter_.get();
|
||||
} while (last_filter);
|
||||
} else {
|
||||
// Only the wrapper exists.
|
||||
filter_list = wrapper.release();
|
||||
}
|
||||
}
|
||||
|
||||
return filter_list;
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ class CefNetworkDelegate : public net::NetworkDelegateImpl {
|
||||
void OnCompleted(net::URLRequest* request, bool started) override;
|
||||
bool OnCanAccessFile(const net::URLRequest& request,
|
||||
const base::FilePath& path) const override;
|
||||
net::Filter* SetupFilter(net::URLRequest* request,
|
||||
net::Filter* filter_list) override;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefNetworkDelegate);
|
||||
};
|
||||
|
@ -577,7 +577,8 @@ void CefResourceRequestJob::FetchResponseCookies(
|
||||
}
|
||||
|
||||
void CefResourceRequestJob::DoneWithRequest() {
|
||||
DCHECK(!done_);
|
||||
if (done_)
|
||||
return;
|
||||
done_ = true;
|
||||
|
||||
if (request_)
|
||||
|
71
libcef/browser/net/response_filter_wrapper.cc
Normal file
71
libcef/browser/net/response_filter_wrapper.cc
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
#include "libcef/browser/net/response_filter_wrapper.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
// FilterType is used for logging purposes only.
|
||||
CefResponseFilterWrapper::CefResponseFilterWrapper(
|
||||
CefRefPtr<CefResponseFilter> cef_filter,
|
||||
bool has_other_filters)
|
||||
: Filter(Filter::FILTER_TYPE_UNSUPPORTED),
|
||||
cef_filter_(cef_filter),
|
||||
has_other_filters_(has_other_filters) {
|
||||
DCHECK(cef_filter_.get());
|
||||
}
|
||||
|
||||
CefResponseFilterWrapper::~CefResponseFilterWrapper() {
|
||||
}
|
||||
|
||||
net::Filter::FilterStatus CefResponseFilterWrapper::ReadFilteredData(
|
||||
char* dest_buffer,
|
||||
int* dest_len) {
|
||||
if (!dest_buffer || !dest_len || *dest_len <= 0)
|
||||
return net::Filter::FILTER_ERROR;
|
||||
|
||||
size_t data_in_size = static_cast<size_t>(stream_data_len_);
|
||||
size_t data_in_read = 0;
|
||||
size_t data_out_size = static_cast<size_t>(*dest_len);
|
||||
size_t data_out_write = 0;
|
||||
|
||||
cef_response_filter_status_t cef_status = cef_filter_->Filter(
|
||||
next_stream_data_, data_in_size, data_in_read,
|
||||
dest_buffer, data_out_size, data_out_write);
|
||||
|
||||
// Return early if there's an error.
|
||||
if (cef_status == RESPONSE_FILTER_ERROR)
|
||||
return net::Filter::FILTER_ERROR;
|
||||
|
||||
// Normalize the out values.
|
||||
if (data_in_read > data_in_size) {
|
||||
LOG(ERROR) <<
|
||||
"potential buffer overflow; data_in_read exceeds data_in_size";
|
||||
data_in_read = data_in_size;
|
||||
}
|
||||
if (data_out_write > data_out_size) {
|
||||
LOG(ERROR) <<
|
||||
"potential buffer overflow; data_out_write exceeds data_out_size";
|
||||
data_out_write = data_out_size;
|
||||
}
|
||||
|
||||
// Output the number of bytes written.
|
||||
*dest_len = static_cast<int>(data_out_write);
|
||||
|
||||
if (data_in_size - data_in_read > 0U) {
|
||||
// There are bytes left so adjust the stream pointer and return FILTER_OK.
|
||||
next_stream_data_ += data_in_read;
|
||||
stream_data_len_ -= static_cast<int>(data_in_read);
|
||||
return Filter::FILTER_OK;
|
||||
}
|
||||
|
||||
// No bytes left. Might need more data or might be done.
|
||||
// If |has_other_filters_| is true then we must return FILTER_NEED_MORE_DATA
|
||||
// or additional data will not be sent.
|
||||
next_stream_data_ = nullptr;
|
||||
stream_data_len_ = 0;
|
||||
if (cef_status == RESPONSE_FILTER_NEED_MORE_DATA || has_other_filters_)
|
||||
return Filter::FILTER_NEED_MORE_DATA;
|
||||
return Filter::FILTER_DONE;
|
||||
}
|
41
libcef/browser/net/response_filter_wrapper.h
Normal file
41
libcef/browser/net/response_filter_wrapper.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2015 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 CEF_LIBCEF_BROWSER_NET_RESPONSE_FILTER_WRAPPER_H_
|
||||
#define CEF_LIBCEF_BROWSER_NET_RESPONSE_FILTER_WRAPPER_H_
|
||||
|
||||
#include "include/cef_response_filter.h"
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "net/filter/filter.h"
|
||||
|
||||
class CefResponseFilterWrapper : public net::Filter {
|
||||
public:
|
||||
CefResponseFilterWrapper(CefRefPtr<CefResponseFilter> cef_filter,
|
||||
bool has_other_filters);
|
||||
~CefResponseFilterWrapper() override;
|
||||
|
||||
// Decodes the pre-filter data and writes the output into the dest_buffer
|
||||
// passed in.
|
||||
// The function returns FilterStatus. See filter.h for its description.
|
||||
//
|
||||
// Upon entry, *dest_len is the total size (in number of chars) of the
|
||||
// destination buffer. Upon exit, *dest_len is the actual number of chars
|
||||
// written into the destination buffer.
|
||||
//
|
||||
// This function will fail if there is no pre-filter data in the
|
||||
// stream_buffer_. On the other hand, *dest_len can be 0 upon successful
|
||||
// return. For example, the internal filter may process some pre-filter data
|
||||
// but not produce output yet.
|
||||
FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len) override;
|
||||
|
||||
private:
|
||||
CefRefPtr<CefResponseFilter> cef_filter_;
|
||||
const bool has_other_filters_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefResponseFilterWrapper);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_NET_RESPONSE_FILTER_WRAPPER_H_
|
Reference in New Issue
Block a user