Add support for response filtering (issue #515).

- Add a new CefRequestHandler::GetResourceResponseFilter method and
  CefResponseFilter class.
This commit is contained in:
Marshall Greenblatt 2015-12-04 21:58:56 -05:00
parent 864db71f6b
commit f207a555a3
40 changed files with 1765 additions and 6 deletions

View File

@ -1055,6 +1055,8 @@
'libcef/browser/net/network_delegate.h',
'libcef/browser/net/resource_request_job.cc',
'libcef/browser/net/resource_request_job.h',
'libcef/browser/net/response_filter_wrapper.cc',
'libcef/browser/net/response_filter_wrapper.h',
'libcef/browser/net/scheme_handler.cc',
'libcef/browser/net/scheme_handler.h',
'libcef/browser/net/url_request_context.cc',

View File

@ -56,6 +56,7 @@
'include/cef_resource_bundle_handler.h',
'include/cef_resource_handler.h',
'include/cef_response.h',
'include/cef_response_filter.h',
'include/cef_scheme.h',
'include/cef_ssl_info.h',
'include/cef_stream.h',
@ -115,6 +116,7 @@
'include/capi/cef_resource_bundle_handler_capi.h',
'include/capi/cef_resource_handler_capi.h',
'include/capi/cef_response_capi.h',
'include/capi/cef_response_filter_capi.h',
'include/capi/cef_scheme_capi.h',
'include/capi/cef_ssl_info_capi.h',
'include/capi/cef_stream_capi.h',
@ -258,6 +260,8 @@
'libcef_dll/ctocpp/resource_handler_ctocpp.h',
'libcef_dll/cpptoc/response_cpptoc.cc',
'libcef_dll/cpptoc/response_cpptoc.h',
'libcef_dll/ctocpp/response_filter_ctocpp.cc',
'libcef_dll/ctocpp/response_filter_ctocpp.h',
'libcef_dll/cpptoc/run_context_menu_callback_cpptoc.cc',
'libcef_dll/cpptoc/run_context_menu_callback_cpptoc.h',
'libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.cc',
@ -456,6 +460,8 @@
'libcef_dll/cpptoc/resource_handler_cpptoc.h',
'libcef_dll/ctocpp/response_ctocpp.cc',
'libcef_dll/ctocpp/response_ctocpp.h',
'libcef_dll/cpptoc/response_filter_cpptoc.cc',
'libcef_dll/cpptoc/response_filter_cpptoc.h',
'libcef_dll/ctocpp/run_context_menu_callback_ctocpp.cc',
'libcef_dll/ctocpp/run_context_menu_callback_ctocpp.h',
'libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.cc',

View File

@ -175,6 +175,8 @@
'tests/cefclient/browser/preferences_test.h',
'tests/cefclient/browser/resource.h',
'tests/cefclient/browser/resource_util.h',
'tests/cefclient/browser/response_filter_test.cc',
'tests/cefclient/browser/response_filter_test.h',
'tests/cefclient/browser/root_window.cc',
'tests/cefclient/browser/root_window.h',
'tests/cefclient/browser/root_window_manager.cc',
@ -223,6 +225,7 @@
'tests/cefclient/resources/performance.html',
'tests/cefclient/resources/performance2.html',
'tests/cefclient/resources/preferences.html',
'tests/cefclient/resources/response_filter.html',
'tests/cefclient/resources/transparency.html',
'tests/cefclient/resources/urlrequest.html',
'tests/cefclient/resources/window.html',

View File

@ -45,6 +45,7 @@
#include "include/capi/cef_request_capi.h"
#include "include/capi/cef_resource_handler_capi.h"
#include "include/capi/cef_response_capi.h"
#include "include/capi/cef_response_filter_capi.h"
#include "include/capi/cef_ssl_info_capi.h"
#ifdef __cplusplus
@ -162,6 +163,16 @@ typedef struct _cef_request_handler_t {
struct _cef_browser_t* browser, struct _cef_frame_t* frame,
struct _cef_request_t* request, struct _cef_response_t* response);
///
// Called on the IO thread to optionally filter resource response content.
// |request| and |response| represent the request and response respectively
// and cannot be modified in this callback.
///
struct _cef_response_filter_t* (CEF_CALLBACK *get_resource_response_filter)(
struct _cef_request_handler_t* self, struct _cef_browser_t* browser,
struct _cef_frame_t* frame, struct _cef_request_t* request,
struct _cef_response_t* response);
///
// Called on the IO thread when a resource load has completed. |request| and
// |response| represent the request and response respectively and cannot be

View File

@ -0,0 +1,91 @@
// Copyright (c) 2015 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef CEF_INCLUDE_CAPI_CEF_RESPONSE_FILTER_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_RESPONSE_FILTER_CAPI_H_
#pragma once
#include "include/capi/cef_base_capi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
// Implement this structure to filter resource response content. The functions
// of this structure will be called on the browser process IO thread.
///
typedef struct _cef_response_filter_t {
///
// Base structure.
///
cef_base_t base;
///
// Initialize the response filter. Will only be called a single time. The
// filter will not be installed if this function returns false (0).
///
int (CEF_CALLBACK *init_filter)(struct _cef_response_filter_t* self);
// Called to filter a chunk of data. |data_in| is the input buffer containing
// |data_in_size| bytes of pre-filter data (|data_in| will be NULL if
// |data_in_size| is zero). |data_out| is the output buffer that can accept up
// to |data_out_size| bytes of filtered output data. Set |data_in_read| to the
// number of bytes that were read from |data_in|. Set |data_out_written| to
// the number of bytes that were written into |data_out|. If some or all of
// the pre-filter data was read successfully but more data is needed in order
// to continue filtering (filtered output is pending) return
// RESPONSE_FILTER_NEED_MORE_DATA. If some or all of the pre-filter data was
// read successfully and all available filtered output has been written return
// RESPONSE_FILTER_DONE. If an error occurs during filtering return
// RESPONSE_FILTER_ERROR. This function will be called repeatedly until there
// is no more data to filter (resource response is complete), |data_in_read|
// matches |data_in_size| (all available pre-filter bytes have been read), and
// the function returns RESPONSE_FILTER_DONE or RESPONSE_FILTER_ERROR. Do not
// keep a reference to the buffers passed to this function.
cef_response_filter_status_t (CEF_CALLBACK *filter)(
struct _cef_response_filter_t* self, void* data_in, size_t data_in_size,
size_t* data_in_read, void* data_out, size_t data_out_size,
size_t* data_out_written);
} cef_response_filter_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_RESPONSE_FILTER_CAPI_H_

View File

@ -44,6 +44,7 @@
#include "include/cef_frame.h"
#include "include/cef_resource_handler.h"
#include "include/cef_response.h"
#include "include/cef_response_filter.h"
#include "include/cef_request.h"
#include "include/cef_ssl_info.h"
@ -181,6 +182,20 @@ class CefRequestHandler : public virtual CefBase {
return false;
}
///
// Called on the IO thread to optionally filter resource response content.
// |request| and |response| represent the request and response respectively
// and cannot be modified in this callback.
///
/*--cef()--*/
virtual CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
return NULL;
}
///
// Called on the IO thread when a resource load has completed. |request| and
// |response| represent the request and response respectively and cannot be

View File

@ -0,0 +1,84 @@
// Copyright (c) 2015 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// The contents of this file must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_RESPONSE_FILTER_H_
#define CEF_INCLUDE_CEF_RESPONSE_FILTER_H_
#pragma once
#include "include/cef_base.h"
///
// Implement this interface to filter resource response content. The methods of
// this class will be called on the browser process IO thread.
///
/*--cef(source=client)--*/
class CefResponseFilter : public virtual CefBase {
public:
typedef cef_response_filter_status_t FilterStatus;
///
// Initialize the response filter. Will only be called a single time. The
// filter will not be installed if this method returns false.
///
/*--cef()--*/
virtual bool InitFilter() =0;
// Called to filter a chunk of data. |data_in| is the input buffer containing
// |data_in_size| bytes of pre-filter data (|data_in| will be NULL if
// |data_in_size| is zero). |data_out| is the output buffer that can accept up
// to |data_out_size| bytes of filtered output data. Set |data_in_read| to the
// number of bytes that were read from |data_in|. Set |data_out_written| to
// the number of bytes that were written into |data_out|. If some or all of
// the pre-filter data was read successfully but more data is needed in order
// to continue filtering (filtered output is pending) return
// RESPONSE_FILTER_NEED_MORE_DATA. If some or all of the pre-filter data was
// read successfully and all available filtered output has been written return
// RESPONSE_FILTER_DONE. If an error occurs during filtering return
// RESPONSE_FILTER_ERROR. This method will be called repeatedly until there is
// no more data to filter (resource response is complete), |data_in_read|
// matches |data_in_size| (all available pre-filter bytes have been read), and
// the method returns RESPONSE_FILTER_DONE or RESPONSE_FILTER_ERROR. Do not
// keep a reference to the buffers passed to this method.
/*--cef(optional_param=data_in,default_retval=RESPONSE_FILTER_ERROR)--*/
virtual FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) =0;
};
#endif // CEF_INCLUDE_CEF_RESPONSE_FILTER_H_

View File

@ -2304,7 +2304,7 @@ typedef enum {
// If the `--no-referrers` command-line flag is specified then the policy value
// will be ignored and the Referrer value will never be sent.
///
typedef enum {
typedef enum {
///
// Always send the complete Referrer value.
///
@ -2341,6 +2341,28 @@ typedef enum {
REFERRER_POLICY_ORIGIN_WHEN_CROSS_ORIGIN,
} cef_referrer_policy_t;
///
// Return values for CefResponseFilter::Filter().
///
typedef enum {
///
// Some or all of the pre-filter data was read successfully but more data is
// needed in order to continue filtering (filtered output is pending).
///
RESPONSE_FILTER_NEED_MORE_DATA,
///
// Some or all of the pre-filter data was read successfully and all available
// filtered output has been written.
///
RESPONSE_FILTER_DONE,
///
// An error occurred during filtering.
///
RESPONSE_FILTER_ERROR
} cef_response_filter_status_t;
#ifdef __cplusplus
}
#endif

View File

@ -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;
}

View File

@ -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);
};

View File

@ -577,7 +577,8 @@ void CefResourceRequestJob::FetchResponseCookies(
}
void CefResourceRequestJob::DoneWithRequest() {
DCHECK(!done_);
if (done_)
return;
done_ = true;
if (request_)

View 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;
}

View 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_

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_handler_cpptoc.h"
#include "libcef_dll/cpptoc/response_filter_cpptoc.h"
#include "libcef_dll/ctocpp/auth_callback_ctocpp.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
@ -234,6 +235,44 @@ int CEF_CALLBACK request_handler_on_resource_response(
return _retval;
}
struct _cef_response_filter_t* CEF_CALLBACK request_handler_get_resource_response_filter(
struct _cef_request_handler_t* self, cef_browser_t* browser,
cef_frame_t* frame, cef_request_t* request,
struct _cef_response_t* response) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return NULL;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
return NULL;
// Verify param: request; type: refptr_diff
DCHECK(request);
if (!request)
return NULL;
// Verify param: response; type: refptr_diff
DCHECK(response);
if (!response)
return NULL;
// Execute
CefRefPtr<CefResponseFilter> _retval = CefRequestHandlerCppToC::Get(
self)->GetResourceResponseFilter(
CefBrowserCToCpp::Wrap(browser),
CefFrameCToCpp::Wrap(frame),
CefRequestCToCpp::Wrap(request),
CefResponseCToCpp::Wrap(response));
// Return type: refptr_same
return CefResponseFilterCppToC::Wrap(_retval);
}
void CEF_CALLBACK request_handler_on_resource_load_complete(
struct _cef_request_handler_t* self, cef_browser_t* browser,
cef_frame_t* frame, cef_request_t* request,
@ -497,6 +536,8 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC() {
GetStruct()->get_resource_handler = request_handler_get_resource_handler;
GetStruct()->on_resource_redirect = request_handler_on_resource_redirect;
GetStruct()->on_resource_response = request_handler_on_resource_response;
GetStruct()->get_resource_response_filter =
request_handler_get_resource_response_filter;
GetStruct()->on_resource_load_complete =
request_handler_on_resource_load_complete;
GetStruct()->get_auth_credentials = request_handler_get_auth_credentials;

View File

@ -0,0 +1,107 @@
// Copyright (c) 2015 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/response_filter_cpptoc.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK response_filter_init_filter(
struct _cef_response_filter_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefResponseFilterCppToC::Get(self)->InitFilter();
// Return type: bool
return _retval;
}
cef_response_filter_status_t CEF_CALLBACK response_filter_filter(
struct _cef_response_filter_t* self, void* data_in, size_t data_in_size,
size_t* data_in_read, void* data_out, size_t data_out_size,
size_t* data_out_written) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return RESPONSE_FILTER_ERROR;
// Verify param: data_in_read; type: simple_byref
DCHECK(data_in_read);
if (!data_in_read)
return RESPONSE_FILTER_ERROR;
// Verify param: data_out; type: simple_byaddr
DCHECK(data_out);
if (!data_out)
return RESPONSE_FILTER_ERROR;
// Verify param: data_out_written; type: simple_byref
DCHECK(data_out_written);
if (!data_out_written)
return RESPONSE_FILTER_ERROR;
// Unverified params: data_in
// Translate param: data_in_read; type: simple_byref
size_t data_in_readVal = data_in_read?*data_in_read:0;
// Translate param: data_out_written; type: simple_byref
size_t data_out_writtenVal = data_out_written?*data_out_written:0;
// Execute
cef_response_filter_status_t _retval = CefResponseFilterCppToC::Get(
self)->Filter(
data_in,
data_in_size,
data_in_readVal,
data_out,
data_out_size,
data_out_writtenVal);
// Restore param: data_in_read; type: simple_byref
if (data_in_read)
*data_in_read = data_in_readVal;
// Restore param: data_out_written; type: simple_byref
if (data_out_written)
*data_out_written = data_out_writtenVal;
// Return type: simple
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefResponseFilterCppToC::CefResponseFilterCppToC() {
GetStruct()->init_filter = response_filter_init_filter;
GetStruct()->filter = response_filter_filter;
}
template<> CefRefPtr<CefResponseFilter> CefCppToC<CefResponseFilterCppToC,
CefResponseFilter, cef_response_filter_t>::UnwrapDerived(
CefWrapperType type, cef_response_filter_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#ifndef NDEBUG
template<> base::AtomicRefCount CefCppToC<CefResponseFilterCppToC,
CefResponseFilter, cef_response_filter_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCppToC<CefResponseFilterCppToC, CefResponseFilter,
cef_response_filter_t>::kWrapperType = WT_RESPONSE_FILTER;

View File

@ -0,0 +1,35 @@
// Copyright (c) 2015 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_RESPONSE_FILTER_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_RESPONSE_FILTER_CPPTOC_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_response_filter.h"
#include "include/capi/cef_response_filter_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefResponseFilterCppToC
: public CefCppToC<CefResponseFilterCppToC, CefResponseFilter,
cef_response_filter_t> {
public:
CefResponseFilterCppToC();
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_RESPONSE_FILTER_CPPTOC_H_

View File

@ -19,6 +19,7 @@
#include "libcef_dll/cpptoc/sslinfo_cpptoc.h"
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_handler_ctocpp.h"
#include "libcef_dll/ctocpp/response_filter_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
@ -226,6 +227,44 @@ bool CefRequestHandlerCToCpp::OnResourceResponse(CefRefPtr<CefBrowser> browser,
return _retval?true:false;
}
CefRefPtr<CefResponseFilter> CefRequestHandlerCToCpp::GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request, CefRefPtr<CefResponse> response) {
cef_request_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_resource_response_filter))
return NULL;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return NULL;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
return NULL;
// Verify param: request; type: refptr_diff
DCHECK(request.get());
if (!request.get())
return NULL;
// Verify param: response; type: refptr_diff
DCHECK(response.get());
if (!response.get())
return NULL;
// Execute
cef_response_filter_t* _retval = _struct->get_resource_response_filter(
_struct,
CefBrowserCppToC::Wrap(browser),
CefFrameCppToC::Wrap(frame),
CefRequestCppToC::Wrap(request),
CefResponseCppToC::Wrap(response));
// Return type: refptr_same
return CefResponseFilterCToCpp::Wrap(_retval);
}
void CefRequestHandlerCToCpp::OnResourceLoadComplete(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request, CefRefPtr<CefResponse> response,

View File

@ -48,6 +48,10 @@ class CefRequestHandlerCToCpp
bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override;
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override;
void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response, URLRequestStatus status,

View File

@ -0,0 +1,79 @@
// Copyright (c) 2015 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/ctocpp/response_filter_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
bool CefResponseFilterCToCpp::InitFilter() {
cef_response_filter_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, init_filter))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->init_filter(_struct);
// Return type: bool
return _retval?true:false;
}
CefResponseFilter::FilterStatus CefResponseFilterCToCpp::Filter(void* data_in,
size_t data_in_size, size_t& data_in_read, void* data_out,
size_t data_out_size, size_t& data_out_written) {
cef_response_filter_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, filter))
return RESPONSE_FILTER_ERROR;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: data_out; type: simple_byaddr
DCHECK(data_out);
if (!data_out)
return RESPONSE_FILTER_ERROR;
// Unverified params: data_in
// Execute
cef_response_filter_status_t _retval = _struct->filter(_struct,
data_in,
data_in_size,
&data_in_read,
data_out,
data_out_size,
&data_out_written);
// Return type: simple
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
CefResponseFilterCToCpp::CefResponseFilterCToCpp() {
}
template<> cef_response_filter_t* CefCToCpp<CefResponseFilterCToCpp,
CefResponseFilter, cef_response_filter_t>::UnwrapDerived(
CefWrapperType type, CefResponseFilter* c) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#ifndef NDEBUG
template<> base::AtomicRefCount CefCToCpp<CefResponseFilterCToCpp,
CefResponseFilter, cef_response_filter_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCToCpp<CefResponseFilterCToCpp, CefResponseFilter,
cef_response_filter_t>::kWrapperType = WT_RESPONSE_FILTER;

View File

@ -0,0 +1,41 @@
// Copyright (c) 2015 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RESPONSE_FILTER_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_RESPONSE_FILTER_CTOCPP_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_response_filter.h"
#include "include/capi/cef_response_filter_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefResponseFilterCToCpp
: public CefCToCpp<CefResponseFilterCToCpp, CefResponseFilter,
cef_response_filter_t> {
public:
CefResponseFilterCToCpp();
// CefResponseFilter methods.
bool InitFilter() override;
FilterStatus Filter(void* data_in, size_t data_in_size, size_t& data_in_read,
void* data_out, size_t data_out_size,
size_t& data_out_written) override;
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_RESPONSE_FILTER_CTOCPP_H_

View File

@ -104,6 +104,7 @@
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_bundle_handler_ctocpp.h"
#include "libcef_dll/ctocpp/resource_handler_ctocpp.h"
#include "libcef_dll/ctocpp/response_filter_ctocpp.h"
#include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h"
#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h"
#include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h"
@ -249,6 +250,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK(base::AtomicRefCountIsZero(
&CefResourceBundleHandlerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefResponseFilterCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(
&CefRunContextMenuCallbackCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(

View File

@ -62,6 +62,7 @@
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_bundle_handler_cpptoc.h"
#include "libcef_dll/cpptoc/resource_handler_cpptoc.h"
#include "libcef_dll/cpptoc/response_filter_cpptoc.h"
#include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h"
#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
#include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h"
@ -241,6 +242,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK(base::AtomicRefCountIsZero(
&CefResourceBundleHandlerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefResourceHandlerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefResponseFilterCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(
&CefRunContextMenuCallbackCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(

View File

@ -80,6 +80,7 @@ enum CefWrapperType {
WT_RESOURCE_BUNDLE_HANDLER,
WT_RESOURCE_HANDLER,
WT_RESPONSE,
WT_RESPONSE_FILTER,
WT_RUN_CONTEXT_MENU_CALLBACK,
WT_RUN_FILE_DIALOG_CALLBACK,
WT_SSLCERT_PRINCIPAL,

View File

@ -241,4 +241,10 @@ patches = [
'name': 'pdfium_print_549365',
'path': '../third_party/pdfium/',
},
{
# Enable support for filtering resource responses.
# https://bitbucket.org/chromiumembedded/cef/issues/515
'name': 'net_filter_515',
'path': '../net/',
},
]

View File

@ -0,0 +1,60 @@
diff --git base/network_delegate.h base/network_delegate.h
index e8d82a3..8b536d7 100644
--- base/network_delegate.h
+++ base/network_delegate.h
@@ -35,6 +35,7 @@ namespace net {
// of net/base here, because we have a net_base library. Forward declarations
// are ok.
class CookieOptions;
+class Filter;
class HttpRequestHeaders;
class HttpResponseHeaders;
class ProxyInfo;
@@ -118,6 +119,13 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
const GURL& target_url,
const GURL& referrer_url) const;
+ // Optionally add a new filter to the filter list. Returns the first filter in
+ // the list.
+ virtual Filter* SetupFilter(URLRequest* request,
+ Filter* filter_list) {
+ return filter_list;
+ }
+
private:
// This is the interface for subclasses of NetworkDelegate to implement. These
// member functions will be called by the respective public notification
diff --git filter/filter.h filter/filter.h
index 1904a8c..8d5f1ec 100644
--- filter/filter.h
+++ filter/filter.h
@@ -57,6 +57,7 @@
#include "net/base/net_export.h"
#include "net/base/sdch_manager.h"
+class CefNetworkDelegate;
class GURL;
namespace net {
@@ -231,6 +232,7 @@ class NET_EXPORT_PRIVATE Filter {
std::string OrderedFilterList() const;
protected:
+ friend class ::CefNetworkDelegate;
friend class GZipUnitTest;
friend class SdchFilterChainingTest;
FRIEND_TEST_ALL_PREFIXES(FilterTest, ThreeFilterChain);
diff --git url_request/url_request_job.cc url_request/url_request_job.cc
index 641c07b..e613c86 100644
--- url_request/url_request_job.cc
+++ url_request/url_request_job.cc
@@ -466,6 +466,9 @@ void URLRequestJob::NotifyHeadersComplete() {
if (request_->status().is_success())
filter_.reset(SetupFilter());
+ if (network_delegate_)
+ filter_.reset(network_delegate_->SetupFilter(request_, filter_.release()));
+
if (!filter_.get()) {
std::string content_length;
request_->GetResponseHeaderByName("content-length", &content_length);

View File

@ -492,6 +492,17 @@ CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
return resource_manager_->GetResourceHandler(browser, frame, request);
}
CefRefPtr<CefResponseFilter> ClientHandler::GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
CEF_REQUIRE_IO_THREAD();
return test_runner::GetResourceResponseFilter(browser, frame, request,
response);
}
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,

View File

@ -227,6 +227,11 @@ class ClientHandler : public CefClient,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE;
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) OVERRIDE;
bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,

View File

@ -54,10 +54,11 @@
#define IDS_PERFORMANCE_HTML 1008
#define IDS_PERFORMANCE2_HTML 1009
#define IDS_PREFERENCES_HTML 1010
#define IDS_TRANSPARENCY_HTML 1011
#define IDS_URLREQUEST_HTML 1012
#define IDS_WINDOW_HTML 1013
#define IDS_XMLHTTPREQUEST_HTML 1014
#define IDS_RESPONSE_FILTER_HTML 1011
#define IDS_TRANSPARENCY_HTML 1012
#define IDS_URLREQUEST_HTML 1013
#define IDS_WINDOW_HTML 1014
#define IDS_XMLHTTPREQUEST_HTML 1015
// Next default values for new objects
//

View File

@ -48,6 +48,7 @@ int GetResourceId(const char* resource_name) {
{"performance.html", IDS_PERFORMANCE_HTML},
{"performance2.html", IDS_PERFORMANCE2_HTML},
{"preferences.html", IDS_PREFERENCES_HTML},
{"response_filter.html", IDS_RESPONSE_FILTER_HTML},
{"transparency.html", IDS_TRANSPARENCY_HTML},
{"urlrequest.html", IDS_URLREQUEST_HTML},
{"window.html", IDS_WINDOW_HTML},

View File

@ -0,0 +1,242 @@
// Copyright (c) 2015 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 "cefclient/browser/response_filter_test.h"
#include <algorithm>
#include <sstream>
#include <string>
#include "include/base/cef_logging.h"
#include "include/cef_command_line.h"
#include "cefclient/common/client_switches.h"
namespace client {
namespace response_filter_test {
namespace {
const char kTestUrl[] = "http://tests/response_filter";
const char kFindString[] = "REPLACE_THIS_STRING";
const char kReplaceString[] = "This is the replaced string!";
// Helper for passing params to Write().
#define WRITE_PARAMS data_out_ptr, data_out_size, data_out_written
// Filter the contents of response_filter.html by replacing all instances of
// |kFindString| with |kReplaceString|. Pass the `--enable-filter-testing`
// command-line flag (which shrinks the buffer size to 32 bytes) to better test
// the logic in this implementation.
class FindReplaceResponseFilter : public CefResponseFilter {
public:
FindReplaceResponseFilter()
: find_match_offset_(0U),
replace_overflow_size_(0U),
replace_count_(0U) {
}
bool InitFilter() OVERRIDE {
const size_t find_size = sizeof(kFindString) - 1;
const size_t replace_size = sizeof(kReplaceString) - 1;
// Determine a reasonable amount of space for find/replace overflow. For
// example, the amount of space required if the search string is
// found/replaced 10 times (plus space for the count).
if (replace_size > find_size)
replace_overflow_size_ = (replace_size - find_size + 3) * 10;
return true;
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) OVERRIDE {
DCHECK((data_in_size == 0U && !data_in) || (data_in_size > 0U && data_in));
DCHECK_EQ(data_in_read, 0U);
DCHECK(data_out);
DCHECK_GT(data_out_size, 0U);
DCHECK_EQ(data_out_written, 0U);
// All data will be read.
data_in_read = data_in_size;
const size_t find_size = sizeof(kFindString) - 1;
const char* data_in_ptr = static_cast<char*>(data_in);
char* data_out_ptr = static_cast<char*>(data_out);
// Reset the overflow.
std::string old_overflow;
if (!overflow_.empty()) {
old_overflow = overflow_;
overflow_.clear();
}
const size_t likely_out_size =
data_in_size + replace_overflow_size_ + old_overflow.size();
if (data_out_size < likely_out_size) {
// We'll likely need to use the overflow buffer. Size it appropriately.
overflow_.reserve(likely_out_size - data_out_size);
}
if (!old_overflow.empty()) {
// Write the overflow from last time.
Write(old_overflow.c_str(), old_overflow.size(), WRITE_PARAMS);
}
// Evaluate each character in the input buffer. Track how many characters in
// a row match kFindString. If kFindString is completely matched then write
// kReplaceString. Otherwise, write the input characters as-is.
for (size_t i = 0U; i < data_in_size; ++i) {
if (data_in_ptr[i] == kFindString[find_match_offset_]) {
// Matched the next character in the find string.
if (++find_match_offset_ == find_size) {
// Complete match of the find string. Write the replace string.
std::stringstream ss;
ss << ++replace_count_ << ". " << kReplaceString;
const std::string& replace_str = ss.str();
Write(replace_str.c_str(), replace_str.size(), WRITE_PARAMS);
// Start over looking for a match.
find_match_offset_ = 0;
}
continue;
}
// Character did not match the find string.
if (find_match_offset_ > 0) {
// Write the portion of the find string that has matched so far.
Write(kFindString, find_match_offset_, WRITE_PARAMS);
// Start over looking for a match.
find_match_offset_ = 0;
}
// Write the current character.
Write(&data_in_ptr[i], 1, WRITE_PARAMS);
}
// If a match is currently in-progress we need more data. Otherwise, we're
// done.
return find_match_offset_ > 0 ?
RESPONSE_FILTER_NEED_MORE_DATA : RESPONSE_FILTER_DONE;
}
private:
inline void Write(const char* str,
size_t str_size,
char*& data_out_ptr,
size_t data_out_size,
size_t& data_out_written) {
// Number of bytes remaining in the output buffer.
const size_t remaining_space = data_out_size - data_out_written;
// Maximum number of bytes we can write into the output buffer.
const size_t max_write = std::min(str_size, remaining_space);
// Write the maximum portion that fits in the output buffer.
if (max_write == 1) {
// Small optimization for single character writes.
*data_out_ptr = str[0];
data_out_ptr += 1;
data_out_written += 1;
} else if (max_write > 1) {
memcpy(data_out_ptr, str, max_write);
data_out_ptr += max_write;
data_out_written += max_write;
}
if (max_write < str_size) {
// Need to write more bytes than will fit in the output buffer. Store the
// remainder in the overflow buffer.
overflow_ += std::string(str + max_write, str_size - max_write);
}
}
// The portion of the find string that is currently matching.
size_t find_match_offset_;
// The likely amount of overflow.
size_t replace_overflow_size_;
// Overflow from the output buffer.
std::string overflow_;
// Number of times the the string was found/replaced.
size_t replace_count_;
IMPLEMENT_REFCOUNTING(FindReplaceResponseFilter);
};
// Filter that writes out all of the contents unchanged.
class PassThruResponseFilter : public CefResponseFilter {
public:
PassThruResponseFilter() {}
bool InitFilter() OVERRIDE {
return true;
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) OVERRIDE {
DCHECK((data_in_size == 0U && !data_in) || (data_in_size > 0U && data_in));
DCHECK_EQ(data_in_read, 0U);
DCHECK(data_out);
DCHECK_GT(data_out_size, 0U);
DCHECK_EQ(data_out_written, 0U);
// All data will be read.
data_in_read = data_in_size;
// Write out the contents unchanged.
data_out_written = std::min(data_in_read, data_out_size);
if (data_out_written > 0)
memcpy(data_out, data_in, data_out_written);
return RESPONSE_FILTER_DONE;
}
private:
IMPLEMENT_REFCOUNTING(PassThruResponseFilter);
};
// Returns true if |url| starts with the value specified via the `--filter-url`
// command-line flag.
bool MatchesFilterURL(const std::string& url) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
if (command_line->HasSwitch(switches::kFilterURL)) {
const std::string& filter_url =
command_line->GetSwitchValue(switches::kFilterURL);
return url.find(filter_url) == 0;
}
return false;
}
} // namespace
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
// Use the find/replace filter on the test URL.
const std::string& url = request->GetURL();
if (url.find(kTestUrl) == 0)
return new FindReplaceResponseFilter();
if (MatchesFilterURL(url))
return new PassThruResponseFilter();
return NULL;
}
} // namespace response_filter_test
} // namespace client

View File

@ -0,0 +1,27 @@
// Copyright (c) 2015 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.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_RESPONSE_FILTER_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_RESPONSE_FILTER_TEST_H_
#pragma once
#include "include/cef_browser.h"
#include "include/cef_request.h"
#include "include/cef_response.h"
#include "include/cef_response_filter.h"
namespace client {
namespace response_filter_test {
// Create a resource response filter. Called from test_runner.cc.
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response);
} // namespace response_filter_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_RESPONSE_FILTER_TEST_H_

View File

@ -19,6 +19,7 @@
#include "cefclient/browser/preferences_test.h"
#include "cefclient/browser/resource.h"
#include "cefclient/browser/resource_util.h"
#include "cefclient/browser/response_filter_test.h"
#include "cefclient/browser/root_window_manager.h"
#include "cefclient/browser/scheme_test.h"
#include "cefclient/browser/urlrequest_test.h"
@ -729,5 +730,15 @@ void RegisterSchemeHandlers() {
scheme_test::RegisterSchemeHandlers();
}
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
// Create the response filter.
return response_filter_test::GetResourceResponseFilter(browser, frame,
request, response);
}
} // namespace test_runner
} // namespace client

View File

@ -44,6 +44,13 @@ void CreateMessageHandlers(MessageHandlerSet& handlers);
// Register scheme handlers for tests.
void RegisterSchemeHandlers();
// Create a resource response filter for tests.
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response);
} // namespace test_runner
} // namespace client

View File

@ -28,6 +28,7 @@ const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
const char kRequestContextPerBrowser[] = "request-context-per-browser";
const char kBackgroundColor[] = "background-color";
const char kEnableGPU[] = "enable-gpu";
const char kFilterURL[] = "filter-url";
} // namespace switches
} // namespace client

View File

@ -22,6 +22,7 @@ extern const char kMouseCursorChangeDisabled[];
extern const char kRequestContextPerBrowser[];
extern const char kBackgroundColor[];
extern const char kEnableGPU[];
extern const char kFilterURL[];
} // namespace switches
} // namespace client

View File

@ -23,6 +23,7 @@
<li><a href="http://tests/pdf">PDF Viewer iframe</a></li>
<li><a href="http://tests/preferences">Preferences</a></li>
<li><a href="http://mrdoob.com/lab/javascript/requestanimationframe/">requestAnimationFrame</a></li>
<li><a href="http://tests/response_filter">Response Filtering</a></li>
<li><a href="client://tests/handler.html">Scheme Handler</a></li>
<li><a href="https://www.google.com/intl/en/chrome/demos/speech.html">Speech Input</a> - requires "enable-speech-input" flag</li>
<li><a href="http://tests/transparency">Transparency</a></li>

View File

@ -0,0 +1,76 @@
<html>
<head>
<title>Response Filter Test</title>
</head>
<body bgcolor="white">
<p>The text shown below in <font color="red">red</font> has been replaced by the filter. This document is > 32kb in order to exceed the standard output buffer size.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>0. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>1. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>2. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>3. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>4. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>5. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>6. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>7. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>8. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p>9. It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to Heaven, we were all going direct the other way -- in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.</p>
<p><font color="red">REPLACE_THIS_STRING</font></p>
<p>End.</p>
</body>
</html>

View File

@ -40,6 +40,7 @@ IDS_PDF_PDF BINARY "..\\pdf.pdf"
IDS_PERFORMANCE_HTML BINARY "..\\performance.html"
IDS_PERFORMANCE2_HTML BINARY "..\\performance2.html"
IDS_PREFERENCES_HTML BINARY "..\\preferences.html"
IDS_RESPONSE_FILTER_HTML BINARY "..\\response_filter.html"
IDS_TRANSPARENCY_HTML BINARY "..\\transparency.html"
IDS_URLREQUEST_HTML BINARY "..\\urlrequest.html"
IDS_WINDOW_HTML BINARY "..\\window.html"

View File

@ -5,6 +5,9 @@
// Include this first to avoid type conflicts with CEF headers.
#include "tests/unittests/chromium_includes.h"
#include <algorithm>
#include <string>
#include "base/strings/stringprintf.h"
#include "include/base/cef_bind.h"
@ -1178,6 +1181,535 @@ TEST(RequestHandlerTest, BeforeResourceLoadContinueAsync) {
}
namespace {
// For response filtering we need to test:
// - Passing through content unchanged.
// - Not reading all of the input buffer.
// - Needing more input and getting it.
// - Needing more input and not getting it.
// - Filter error.
const char kResponseFilterTestUrl[] = "http://tests.com/response_filter.html";
const size_t kResponseBufferSize = 1024 * 32; // 32kb
const char kInputHeader[] = "<html><head></head><body>";
const char kInputFooter[] = "</body></html>";
// Repeat |content| the minimum number of times necessary to satisfy
// |desired_min_size|. If |calculated_repeat_ct| is non-NULL it will be set to
// the number of times that |content| was repeated.
std::string CreateInput(const std::string& content,
size_t desired_min_size,
size_t* calculated_repeat_ct = nullptr) {
const size_t header_footer_size =
sizeof(kInputHeader) + sizeof(kInputFooter) - 2;
EXPECT_GE(desired_min_size, header_footer_size + content.size());
desired_min_size -= header_footer_size;
size_t repeat_ct = static_cast<size_t>(
std::ceil(static_cast<double>(desired_min_size) /
static_cast<double>(content.size())));
if (calculated_repeat_ct)
*calculated_repeat_ct = repeat_ct;
std::string result;
result.reserve(header_footer_size + (content.size() * repeat_ct));
result = kInputHeader;
while (repeat_ct--)
result += content;
result += kInputFooter;
return result;
}
std::string CreateOutput(const std::string& content,
size_t repeat_ct) {
const size_t header_footer_size =
sizeof(kInputHeader) + sizeof(kInputFooter) - 2;
std::string result;
result.reserve(header_footer_size + (content.size() * repeat_ct));
result = kInputHeader;
while (repeat_ct--)
result += content;
result += kInputFooter;
return result;
}
// Base class for test filters.
class ResponseFilterTestBase : public CefResponseFilter {
public:
ResponseFilterTestBase()
: filter_count_(0U) {
}
bool InitFilter() override {
EXPECT_FALSE(got_init_filter_);
got_init_filter_.yes();
return true;
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) override {
if (data_in_size == 0U)
EXPECT_FALSE(data_in);
else
EXPECT_TRUE(data_in);
EXPECT_EQ(data_in_read, 0U);
EXPECT_TRUE(data_out);
EXPECT_GT(data_out_size, 0U);
EXPECT_EQ(data_out_written, 0U);
filter_count_++;
return RESPONSE_FILTER_ERROR;
}
// Returns the input that will be fed into the filter.
virtual std::string GetInput() = 0;
// Verify the output from the filter.
virtual void VerifyOutput(cef_urlrequest_status_t status,
int64 received_content_length,
const std::string& received_content) {
EXPECT_TRUE(got_init_filter_);
EXPECT_GT(filter_count_, 0U);
}
protected:
TrackCallback got_init_filter_;
size_t filter_count_;
IMPLEMENT_REFCOUNTING(ResponseFilterTestBase);
};
// Pass through the contents unchanged.
class ResponseFilterPassThru : public ResponseFilterTestBase {
public:
explicit ResponseFilterPassThru(bool limit_read)
: limit_read_(limit_read) {
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) override {
ResponseFilterTestBase::Filter(data_in, data_in_size, data_in_read,
data_out, data_out_size, data_out_written);
if (limit_read_) {
// Read at most 1k bytes.
data_in_read = std::min(data_in_size, static_cast<size_t>(1024U));
} else {
// Read all available bytes.
data_in_read = data_in_size;
}
data_out_written = std::min(data_in_read, data_out_size);
memcpy(data_out, data_in, data_out_written);
return RESPONSE_FILTER_DONE;
}
std::string GetInput() override {
input_ = CreateInput("FOOBAR ", kResponseBufferSize * 2U);
return input_;
}
void VerifyOutput(cef_urlrequest_status_t status,
int64 received_content_length,
const std::string& received_content) override {
ResponseFilterTestBase::VerifyOutput(status, received_content_length,
received_content);
if (limit_read_)
// Expected to read 2 full buffers of kResponseBufferSize at 1kb
// increments (2 * 32) and one partial buffer.
EXPECT_EQ(filter_count_, 2U * 32U + 1U);
else {
// Expected to read 2 full buffers of kResponseBufferSize and one partial
// buffer.
EXPECT_EQ(filter_count_, 3U);
}
EXPECT_STREQ(input_.c_str(), received_content.c_str());
// Input size and content size should match.
EXPECT_EQ(input_.size(), static_cast<size_t>(received_content_length));
EXPECT_EQ(input_.size(), received_content.size());
}
private:
std::string input_;
bool limit_read_;
};
const char kFindString[] = "REPLACE_THIS_STRING";
const char kReplaceString[] = "This is the replaced string!";
// Helper for passing params to Write().
#define WRITE_PARAMS data_out_ptr, data_out_size, data_out_written
// Replace all instances of |kFindString| with |kReplaceString|.
// This implementation is similar to the example in
// tests/cefclient/response_filter_test.cc.
class ResponseFilterNeedMore : public ResponseFilterTestBase {
public:
ResponseFilterNeedMore()
: find_match_offset_(0U),
replace_overflow_size_(0U),
input_size_(0U),
repeat_ct_(0U) {
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) override {
ResponseFilterTestBase::Filter(data_in, data_in_size, data_in_read,
data_out, data_out_size, data_out_written);
// All data will be read.
data_in_read = data_in_size;
const size_t find_size = sizeof(kFindString) - 1;
const char* data_in_ptr = static_cast<char*>(data_in);
char* data_out_ptr = static_cast<char*>(data_out);
// Reset the overflow.
std::string old_overflow;
if (!overflow_.empty()) {
old_overflow = overflow_;
overflow_.clear();
}
const size_t likely_out_size =
data_in_size + replace_overflow_size_ + old_overflow.size();
if (data_out_size < likely_out_size) {
// We'll likely need to use the overflow buffer. Size it appropriately.
overflow_.reserve(likely_out_size - data_out_size);
}
if (!old_overflow.empty()) {
// Write the overflow from last time.
Write(old_overflow.c_str(), old_overflow.size(), WRITE_PARAMS);
}
// Evaluate each character in the input buffer. Track how many characters in
// a row match kFindString. If kFindString is completely matched then write
// kReplaceString. Otherwise, write the input characters as-is.
for (size_t i = 0U; i < data_in_size; ++i) {
if (data_in_ptr[i] == kFindString[find_match_offset_]) {
// Matched the next character in the find string.
if (++find_match_offset_ == find_size) {
// Complete match of the find string. Write the replace string.
Write(kReplaceString, sizeof(kReplaceString) - 1, WRITE_PARAMS);
// Start over looking for a match.
find_match_offset_ = 0;
}
continue;
}
// Character did not match the find string.
if (find_match_offset_ > 0) {
// Write the portion of the find string that has matched so far.
Write(kFindString, find_match_offset_, WRITE_PARAMS);
// Start over looking for a match.
find_match_offset_ = 0;
}
// Write the current character.
Write(&data_in_ptr[i], 1, WRITE_PARAMS);
}
// If a match is currently in-progress we need more data. Otherwise, we're
// done.
return find_match_offset_ > 0 ?
RESPONSE_FILTER_NEED_MORE_DATA : RESPONSE_FILTER_DONE;
}
std::string GetInput() override {
const std::string& input =
CreateInput(std::string(kFindString) + " ", kResponseBufferSize * 2U,
&repeat_ct_);
input_size_ = input.size();
const size_t find_size = sizeof(kFindString) - 1;
const size_t replace_size = sizeof(kReplaceString) - 1;
// Determine a reasonable amount of space for find/replace overflow.
if (replace_size > find_size)
replace_overflow_size_ = (replace_size - find_size) * repeat_ct_;
return input;
}
void VerifyOutput(cef_urlrequest_status_t status,
int64 received_content_length,
const std::string& received_content) override {
ResponseFilterTestBase::VerifyOutput(status, received_content_length,
received_content);
const std::string& output =
CreateOutput(std::string(kReplaceString) + " ", repeat_ct_);
EXPECT_STREQ(output.c_str(), received_content.c_str());
// Pre-filter content length should be the original input size.
EXPECT_EQ(input_size_, static_cast<size_t>(received_content_length));
// Filtered content length should be the output size.
EXPECT_EQ(output.size(), received_content.size());
// Expected to read 2 full buffers of kResponseBufferSize and one partial
// buffer, and then one additional call to drain the overflow.
EXPECT_EQ(filter_count_, 4U);
}
private:
inline void Write(const char* str,
size_t str_size,
char*& data_out_ptr,
size_t data_out_size,
size_t& data_out_written) {
// Number of bytes remaining in the output buffer.
const size_t remaining_space = data_out_size - data_out_written;
// Maximum number of bytes we can write into the output buffer.
const size_t max_write = std::min(str_size, remaining_space);
// Write the maximum portion that fits in the output buffer.
if (max_write == 1) {
// Small optimization for single character writes.
*data_out_ptr = str[0];
data_out_ptr += 1;
data_out_written += 1;
} else if (max_write > 1) {
memcpy(data_out_ptr, str, max_write);
data_out_ptr += max_write;
data_out_written += max_write;
}
if (max_write < str_size) {
// Need to write more bytes than will fit in the output buffer. Store the
// remainder in the overflow buffer.
overflow_ += std::string(str + max_write, str_size - max_write);
}
}
// The portion of the find string that is currently matching.
size_t find_match_offset_;
// The likely amount of overflow.
size_t replace_overflow_size_;
// Overflow from the output buffer.
std::string overflow_;
// The original input size.
size_t input_size_;
// The number of times the find string was repeated.
size_t repeat_ct_;
};
// Return a filter error.
class ResponseFilterError : public ResponseFilterTestBase {
public:
ResponseFilterError() {
}
FilterStatus Filter(void* data_in,
size_t data_in_size,
size_t& data_in_read,
void* data_out,
size_t data_out_size,
size_t& data_out_written) override {
ResponseFilterTestBase::Filter(data_in, data_in_size, data_in_read,
data_out, data_out_size, data_out_written);
return RESPONSE_FILTER_ERROR;
}
std::string GetInput() override {
return kInputHeader + std::string("ERROR") + kInputFooter;
}
void VerifyOutput(cef_urlrequest_status_t status,
int64 received_content_length,
const std::string& received_content) override {
ResponseFilterTestBase::VerifyOutput(status, received_content_length,
received_content);
EXPECT_EQ(UR_FAILED, status);
// Expect empty content.
const std::string& output = std::string(kInputHeader) + kInputFooter;
EXPECT_STREQ(output.c_str(), received_content.c_str());
EXPECT_EQ(0U, received_content_length);
// Expect to only be called one time.
EXPECT_EQ(filter_count_, 1U);
}
};
// Browser side.
class ResponseFilterTestHandler : public TestHandler {
public:
explicit ResponseFilterTestHandler(
CefRefPtr<ResponseFilterTestBase> response_filter)
: response_filter_(response_filter) {}
void RunTest() override {
const std::string& resource = response_filter_->GetInput();
AddResource(kResponseFilterTestUrl, resource, "text/html");
// Create the browser.
CreateBrowser(kResponseFilterTestUrl);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override {
EXPECT_IO_THREAD();
DCHECK(!got_resource_response_filter_);
got_resource_response_filter_.yes();
return response_filter_;
}
void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response,
URLRequestStatus status,
int64 received_content_length) override {
EXPECT_IO_THREAD();
DCHECK(!got_resource_load_complete_);
got_resource_load_complete_.yes();
status_ = status;
received_content_length_ = received_content_length;
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
DCHECK(!got_load_end_);
got_load_end_.yes();
EXPECT_EQ(200, httpStatusCode);
GetOutputContent(frame);
}
private:
// Retrieve the output content using a StringVisitor. This effectively
// serializes the DOM from the renderer process so any comparison to the
// filter output is somewhat error-prone.
void GetOutputContent(CefRefPtr<CefFrame> frame) {
class StringVisitor : public CefStringVisitor {
public:
typedef base::Callback<void(const std::string& /*received_content*/)>
VisitorCallback;
explicit StringVisitor(const VisitorCallback& callback)
: callback_(callback) {}
void Visit(const CefString& string) override {
callback_.Run(string);
callback_.Reset();
}
private:
VisitorCallback callback_;
IMPLEMENT_REFCOUNTING(StringVisitor);
};
frame->GetSource(new StringVisitor(
base::Bind(&ResponseFilterTestHandler::VerifyOutput, this)));
}
void VerifyOutput(const std::string& received_content) {
response_filter_->VerifyOutput(status_, received_content_length_,
received_content);
response_filter_ = nullptr;
DestroyTest();
}
void DestroyTest() override {
EXPECT_TRUE(got_resource_response_filter_);
EXPECT_TRUE(got_resource_load_complete_);
EXPECT_TRUE(got_load_end_);
TestHandler::DestroyTest();
}
CefRefPtr<ResponseFilterTestBase> response_filter_;
TrackCallback got_resource_response_filter_;
TrackCallback got_resource_load_complete_;
TrackCallback got_load_end_;
URLRequestStatus status_;
int64 received_content_length_;
IMPLEMENT_REFCOUNTING(ResponseFilterTestHandler);
};
} // namespace
// Pass through contents unchanged. Read all available input.
TEST(RequestHandlerTest, ResponseFilterPassThruReadAll) {
CefRefPtr<ResponseFilterTestHandler> handler =
new ResponseFilterTestHandler(new ResponseFilterPassThru(false));
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Pass through contents unchanged. Read limited input.
TEST(RequestHandlerTest, ResponseFilterPassThruReadLimited) {
CefRefPtr<ResponseFilterTestHandler> handler =
new ResponseFilterTestHandler(new ResponseFilterPassThru(true));
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Find/replace contents such that we occasionally need more data.
TEST(RequestHandlerTest, ResponseFilterNeedMore) {
CefRefPtr<ResponseFilterTestHandler> handler =
new ResponseFilterTestHandler(new ResponseFilterNeedMore());
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Error during filtering.
TEST(RequestHandlerTest, ResponseFilterError) {
CefRefPtr<ResponseFilterTestHandler> handler =
new ResponseFilterTestHandler(new ResponseFilterError());
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Entry point for creating request handler browser test objects.
// Called from client_app_delegates.cc.
void CreateRequestHandlerBrowserTests(

View File

@ -231,6 +231,22 @@ class RequestSendRecvTestHandler : public TestHandler {
return false;
}
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override {
EXPECT_IO_THREAD();
TestRequest(request);
EXPECT_TRUE(request->IsReadOnly());
TestResponse(response);
EXPECT_TRUE(response->IsReadOnly());
got_resource_response_filter_.yes();
return NULL;
}
void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
@ -269,6 +285,7 @@ class RequestSendRecvTestHandler : public TestHandler {
EXPECT_TRUE(got_before_resource_load_);
EXPECT_TRUE(got_resource_handler_);
EXPECT_TRUE(got_resource_response_);
EXPECT_TRUE(got_resource_response_filter_);
EXPECT_TRUE(got_resource_load_complete_);
TestHandler::DestroyTest();
@ -281,6 +298,7 @@ class RequestSendRecvTestHandler : public TestHandler {
TrackCallback got_before_resource_load_;
TrackCallback got_resource_handler_;
TrackCallback got_resource_response_;
TrackCallback got_resource_response_filter_;
TrackCallback got_resource_load_complete_;
IMPLEMENT_REFCOUNTING(RequestSendRecvTestHandler);