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