Modify CefResponse header methods to match CefRequest API (fixes issue #2770)

This commit is contained in:
Mike Wiedenbauer 2019-10-14 13:32:38 +02:00 committed by Marshall Greenblatt
parent 9cdda243a1
commit 1d515adc22
16 changed files with 231 additions and 50 deletions

1
.gitignore vendored
View File

@ -35,6 +35,7 @@
.metadata
.project
.pydevproject
.vscode
# Settings directory for eclipse
/.settings
.checkstyle

View File

@ -490,6 +490,7 @@
'tests/ceftests/request_context_unittest.cc',
'tests/ceftests/request_handler_unittest.cc',
'tests/ceftests/request_unittest.cc',
'tests/ceftests/response_unittest.cc',
'tests/ceftests/resource.h',
'tests/ceftests/resource_manager_unittest.cc',
'tests/ceftests/resource_request_handler_unittest.cc',
@ -564,6 +565,7 @@
'tests/ceftests/process_message_unittest.cc',
'tests/ceftests/request_handler_unittest.cc',
'tests/ceftests/request_unittest.cc',
'tests/ceftests/response_unittest.cc',
'tests/ceftests/resource_request_handler_unittest.cc',
'tests/ceftests/routing_test_handler.cc',
'tests/ceftests/routing_test_handler.h',

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=cc5ec5ca76adb568adb08c3b58fb3289a94b2ecd$
// $hash=67776173c2e8c45b7261af692af96084cdd618ec$
//
#ifndef CEF_INCLUDE_CAPI_CEF_RESPONSE_CAPI_H_
@ -126,9 +126,20 @@ typedef struct _cef_response_t {
// Get the value for the specified response header field.
///
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t(CEF_CALLBACK* get_header)(struct _cef_response_t* self,
cef_string_userfree_t(CEF_CALLBACK* get_header_by_name)(
struct _cef_response_t* self,
const cef_string_t* name);
///
// Set the header |name| to |value|. If |overwrite| is true (1) any existing
// values will be replaced with the new value. If |overwrite| is false (0) any
// existing values will not be overwritten.
///
void(CEF_CALLBACK* set_header_by_name)(struct _cef_response_t* self,
const cef_string_t* name,
const cef_string_t* value,
int overwrite);
///
// Get all response header fields.
///

View File

@ -34,7 +34,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=e1836e5dade0a6f19f058dbfd55df881f454d1e3$
// $hash=42f531d8211496faa76ffa838a2cf0b9cfa45c56$
//
#ifndef CEF_INCLUDE_API_HASH_H_
@ -47,13 +47,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "14afb7265af06a50b900ddd775adc235dc34ec77"
#define CEF_API_HASH_UNIVERSAL "842f5e9a25404c0d6d6408d361c760f1f107b129"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "228f8ff0c24b688aa36db6f0bf88b0c301738c1a"
#define CEF_API_HASH_PLATFORM "f691a75408d8ea7742a14db07fc1df73555320a3"
#elif defined(OS_MACOSX)
#define CEF_API_HASH_PLATFORM "dd1c23009c1356fcb066f195af3da9fcf3175799"
#define CEF_API_HASH_PLATFORM "1c2b7de4554429cfb71302d465cb55e6da45788d"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "ebc0f044eab1238ff313ad4496dd2ff22bd261ec"
#define CEF_API_HASH_PLATFORM "698c65121d173f8a72997e91783166a930c2efca"
#endif
#ifdef __cplusplus

View File

@ -127,7 +127,17 @@ class CefResponse : public virtual CefBaseRefCounted {
// Get the value for the specified response header field.
///
/*--cef()--*/
virtual CefString GetHeader(const CefString& name) = 0;
virtual CefString GetHeaderByName(const CefString& name) = 0;
///
// Set the header |name| to |value|. If |overwrite| is true any existing
// values will be replaced with the new value. If |overwrite| is false any
// existing values will not be overwritten.
///
/*--cef(optional_param=value)--*/
virtual void SetHeaderByName(const CefString& name,
const CefString& value,
bool overwrite) = 0;
///
// Get all response header fields.

View File

@ -4,6 +4,9 @@
#include "libcef/common/net/http_header_utils.h"
#include <algorithm>
#include "base/strings/string_util.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@ -40,4 +43,18 @@ void ParseHeaders(const std::string& header_str, HeaderMap& map) {
}
}
void MakeASCIILower(std::string* str) {
std::transform(str->begin(), str->end(), str->begin(), ::tolower);
}
HeaderMap::iterator FindHeaderInMap(const std::string& nameLower,
HeaderMap& map) {
for (auto it = map.begin(); it != map.end(); ++it) {
if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower))
return it;
}
return map.end();
}
} // namespace HttpHeaderUtils

View File

@ -6,17 +6,25 @@
#define CEF_LIBCEF_COMMON_NET_HTTP_HEADER_UTILS_H_
#pragma once
#include <map>
#include <string>
#include "include/cef_request.h"
#include "include/cef_base.h"
namespace HttpHeaderUtils {
typedef CefRequest::HeaderMap HeaderMap;
typedef std::multimap<CefString, CefString> HeaderMap;
std::string GenerateHeaders(const HeaderMap& map);
void ParseHeaders(const std::string& header_str, HeaderMap& map);
// Convert |str| to lower-case.
void MakeASCIILower(std::string* str);
// Finds the first instance of |name| (already lower-case) in |map| with
// case-insensitive comparison.
HeaderMap::iterator FindHeaderInMap(const std::string& name, HeaderMap& map);
} // namespace HttpHeaderUtils
#endif // CEF_LIBCEF_COMMON_NET_HTTP_HEADER_UTILS_H_

View File

@ -100,10 +100,6 @@ class FileElementReader : public net::UploadFileElementReader {
DISALLOW_COPY_AND_ASSIGN(FileElementReader);
};
void MakeASCIILower(std::string* str) {
std::transform(str->begin(), str->end(), str->begin(), ::tolower);
}
// Returns the cef_urlrequest_flags_t policy specified by the Cache-Control
// request header directives, if any. The directives are case-insensitive and
// some have an optional argument. Multiple directives are comma-separated.
@ -127,7 +123,7 @@ int GetCacheControlHeaderPolicy(CefRequest::HeaderMap headerMap) {
int flags = 0;
if (!line.empty()) {
MakeASCIILower(&line);
HttpHeaderUtils::MakeASCIILower(&line);
std::vector<base::StringPiece> pieces = base::SplitStringPiece(
line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
@ -221,18 +217,6 @@ void SetHeaderMap(const CefRequest::HeaderMap& map,
}
}
// Finds the first instance of |nameLower| (already lower-case) in |map| with
// case-insensitive comparison.
CefRequest::HeaderMap::iterator FindHeaderInMap(const std::string& nameLower,
CefRequest::HeaderMap& map) {
for (auto it = map.begin(); it != map.end(); ++it) {
if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower))
return it;
}
return map.end();
}
// Type used in UploadDataStream.
typedef std::vector<std::unique_ptr<net::UploadElementReader>>
UploadElementReaders;
@ -362,9 +346,9 @@ CefString CefRequestImpl::GetHeaderByName(const CefString& name) {
base::AutoLock lock_scope(lock_);
std::string nameLower = name;
MakeASCIILower(&nameLower);
HttpHeaderUtils::MakeASCIILower(&nameLower);
auto it = FindHeaderInMap(nameLower, headermap_);
auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, headermap_);
if (it != headermap_.end())
return it->second;
@ -378,7 +362,7 @@ void CefRequestImpl::SetHeaderByName(const CefString& name,
CHECK_READONLY_RETURN_VOID();
std::string nameLower = name;
MakeASCIILower(&nameLower);
HttpHeaderUtils::MakeASCIILower(&nameLower);
// Do not include Referer in the header map.
if (nameLower == kReferrerLowerCase)

View File

@ -6,6 +6,7 @@
#include <string>
#include "libcef/common/net/http_header_utils.h"
#include "libcef/common/net_service/net_service_util.h"
#include "base/logging.h"
@ -96,16 +97,40 @@ void CefResponseImpl::SetCharset(const CefString& charset) {
charset_ = charset;
}
CefString CefResponseImpl::GetHeader(const CefString& name) {
CefString CefResponseImpl::GetHeaderByName(const CefString& name) {
base::AutoLock lock_scope(lock_);
CefString value;
std::string nameLower = name;
HttpHeaderUtils::MakeASCIILower(&nameLower);
HeaderMap::const_iterator it = header_map_.find(name);
auto it = HttpHeaderUtils::FindHeaderInMap(nameLower, header_map_);
if (it != header_map_.end())
value = it->second;
return it->second;
return value;
return CefString();
}
void CefResponseImpl::SetHeaderByName(const CefString& name,
const CefString& value,
bool overwrite) {
base::AutoLock lock_scope(lock_);
CHECK_READONLY_RETURN_VOID();
std::string nameLower = name;
HttpHeaderUtils::MakeASCIILower(&nameLower);
// There may be multiple values, so remove any first.
for (auto it = header_map_.begin(); it != header_map_.end();) {
if (base::EqualsCaseInsensitiveASCII(it->first.ToString(), nameLower)) {
if (!overwrite)
return;
it = header_map_.erase(it);
} else {
++it;
}
}
header_map_.insert(std::make_pair(name, value));
}
CefString CefResponseImpl::GetURL() {

View File

@ -35,7 +35,10 @@ class CefResponseImpl : public CefResponse {
void SetMimeType(const CefString& mimeType) override;
CefString GetCharset() override;
void SetCharset(const CefString& charset) override;
CefString GetHeader(const CefString& name) override;
CefString GetHeaderByName(const CefString& name) override;
void SetHeaderByName(const CefString& name,
const CefString& value,
bool overwrite) override;
void GetHeaderMap(HeaderMap& headerMap) override;
void SetHeaderMap(const HeaderMap& headerMap) override;
CefString GetURL() override;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=5c6b14610ef7bcadf5e4936a262c660896a32526$
// $hash=f4a89951c1d04bd2c48dceed80e10b1e281a1d24$
//
#include "libcef_dll/cpptoc/response_cpptoc.h"
@ -182,7 +182,8 @@ void CEF_CALLBACK response_set_charset(struct _cef_response_t* self,
}
cef_string_userfree_t CEF_CALLBACK
response_get_header(struct _cef_response_t* self, const cef_string_t* name) {
response_get_header_by_name(struct _cef_response_t* self,
const cef_string_t* name) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
@ -194,12 +195,33 @@ response_get_header(struct _cef_response_t* self, const cef_string_t* name) {
return NULL;
// Execute
CefString _retval = CefResponseCppToC::Get(self)->GetHeader(CefString(name));
CefString _retval =
CefResponseCppToC::Get(self)->GetHeaderByName(CefString(name));
// Return type: string
return _retval.DetachToUserFree();
}
void CEF_CALLBACK response_set_header_by_name(struct _cef_response_t* self,
const cef_string_t* name,
const cef_string_t* value,
int overwrite) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: name; type: string_byref_const
DCHECK(name);
if (!name)
return;
// Unverified params: value
// Execute
CefResponseCppToC::Get(self)->SetHeaderByName(
CefString(name), CefString(value), overwrite ? true : false);
}
void CEF_CALLBACK response_get_header_map(struct _cef_response_t* self,
cef_string_multimap_t headerMap) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -288,7 +310,8 @@ CefResponseCppToC::CefResponseCppToC() {
GetStruct()->set_mime_type = response_set_mime_type;
GetStruct()->get_charset = response_get_charset;
GetStruct()->set_charset = response_set_charset;
GetStruct()->get_header = response_get_header;
GetStruct()->get_header_by_name = response_get_header_by_name;
GetStruct()->set_header_by_name = response_set_header_by_name;
GetStruct()->get_header_map = response_get_header_map;
GetStruct()->set_header_map = response_set_header_map;
GetStruct()->get_url = response_get_url;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=0c197661e7e3e905b90bec127ff7b1ff23240fa2$
// $hash=40590f49f3e6fb36f98cf2e88558def58d41b58e$
//
#include "libcef_dll/ctocpp/response_ctocpp.h"
@ -185,9 +185,9 @@ void CefResponseCToCpp::SetCharset(const CefString& charset) {
}
NO_SANITIZE("cfi-icall")
CefString CefResponseCToCpp::GetHeader(const CefString& name) {
CefString CefResponseCToCpp::GetHeaderByName(const CefString& name) {
cef_response_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_header))
if (CEF_MEMBER_MISSING(_struct, get_header_by_name))
return CefString();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -199,7 +199,7 @@ CefString CefResponseCToCpp::GetHeader(const CefString& name) {
// Execute
cef_string_userfree_t _retval =
_struct->get_header(_struct, name.GetStruct());
_struct->get_header_by_name(_struct, name.GetStruct());
// Return type: string
CefString _retvalStr;
@ -207,6 +207,27 @@ CefString CefResponseCToCpp::GetHeader(const CefString& name) {
return _retvalStr;
}
NO_SANITIZE("cfi-icall")
void CefResponseCToCpp::SetHeaderByName(const CefString& name,
const CefString& value,
bool overwrite) {
cef_response_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_header_by_name))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: name; type: string_byref_const
DCHECK(!name.empty());
if (name.empty())
return;
// Unverified params: value
// Execute
_struct->set_header_by_name(_struct, name.GetStruct(), value.GetStruct(),
overwrite);
}
NO_SANITIZE("cfi-icall")
void CefResponseCToCpp::GetHeaderMap(HeaderMap& headerMap) {
cef_response_t* _struct = GetStruct();

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=529b0d3676e398d5047eb714a8210fefcc937e76$
// $hash=8ebf9fb3b9657402c801523ad86ca9773511a86b$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_RESPONSE_CTOCPP_H_
@ -45,7 +45,10 @@ class CefResponseCToCpp : public CefCToCppRefCounted<CefResponseCToCpp,
void SetMimeType(const CefString& mimeType) OVERRIDE;
CefString GetCharset() OVERRIDE;
void SetCharset(const CefString& charset) OVERRIDE;
CefString GetHeader(const CefString& name) OVERRIDE;
CefString GetHeaderByName(const CefString& name) OVERRIDE;
void SetHeaderByName(const CefString& name,
const CefString& value,
bool overwrite) OVERRIDE;
void GetHeaderMap(HeaderMap& headerMap) OVERRIDE;
void SetHeaderMap(const HeaderMap& headerMap) OVERRIDE;
CefString GetURL() OVERRIDE;

View File

@ -2181,7 +2181,7 @@ class CookieRestartTestHandler : public RoutingTestHandler,
resource_response_ct_++;
const std::string& url = request->GetURL();
const std::string& set_cookie_str = response->GetHeader("Set-Cookie");
const std::string& set_cookie_str = response->GetHeaderByName("Set-Cookie");
// Expect the network cookie with URL1 requests only.
if (resource_response_ct_ <= 2) {

View File

@ -848,7 +848,8 @@ class RedirectTestHandler : public TestHandler {
EXPECT_EQ(302, response->GetStatus());
EXPECT_STREQ("Found", response->GetStatusText().ToString().c_str());
EXPECT_STREQ("", response->GetMimeType().ToString().c_str());
EXPECT_STREQ(kRNav2, response->GetHeader("Location").ToString().c_str());
EXPECT_STREQ(kRNav2,
response->GetHeaderByName("Location").ToString().c_str());
// Change the redirect to the 3rd URL.
new_url = kRNav3;
@ -860,7 +861,8 @@ class RedirectTestHandler : public TestHandler {
EXPECT_STREQ("Internal Redirect",
response->GetStatusText().ToString().c_str());
EXPECT_TRUE(response->GetMimeType().empty());
EXPECT_STREQ(kRNav3, response->GetHeader("Location").ToString().c_str());
EXPECT_STREQ(kRNav3,
response->GetHeaderByName("Location").ToString().c_str());
} else if (old_url == kRNav3 && new_url == kRNav4) {
// Called due to the nav3 redirect response.
got_nav3_redirect_.yes();

View File

@ -0,0 +1,71 @@
// Copyright (c) 2019 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 "include/cef_response.h"
#include "tests/ceftests/test_util.h"
#include "tests/gtest/include/gtest/gtest.h"
TEST(ResponseTest, SetGetHeaderByName) {
CefRefPtr<CefResponse> response(CefResponse::Create());
EXPECT_TRUE(response.get() != NULL);
CefResponse::HeaderMap headers, expectedHeaders;
response->SetHeaderByName("HeaderA", "ValueA", false);
response->SetHeaderByName("HeaderB", "ValueB", false);
expectedHeaders.insert(std::make_pair("HeaderA", "ValueA"));
expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
// Case insensitive retrieval.
EXPECT_STREQ("ValueA",
response->GetHeaderByName("headera").ToString().c_str());
EXPECT_STREQ("ValueB",
response->GetHeaderByName("headerb").ToString().c_str());
EXPECT_STREQ("", response->GetHeaderByName("noexist").ToString().c_str());
response->GetHeaderMap(headers);
TestMapEqual(expectedHeaders, headers, false);
// Replace an existing value.
response->SetHeaderByName("HeaderA", "ValueANew", true);
expectedHeaders.clear();
expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
// Case insensitive retrieval.
EXPECT_STREQ("ValueANew",
response->GetHeaderByName("headerA").ToString().c_str());
response->GetHeaderMap(headers);
TestMapEqual(expectedHeaders, headers, false);
// Header with multiple values.
expectedHeaders.clear();
expectedHeaders.insert(std::make_pair("HeaderA", "ValueA1"));
expectedHeaders.insert(std::make_pair("HeaderA", "ValueA2"));
expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
response->SetHeaderMap(expectedHeaders);
// When there are multiple values only the first is returned.
EXPECT_STREQ("ValueA1",
response->GetHeaderByName("headera").ToString().c_str());
// Don't overwrite the value.
response->SetHeaderByName("HeaderA", "ValueANew", false);
response->GetHeaderMap(headers);
TestMapEqual(expectedHeaders, headers, false);
// Overwrite the value (remove the duplicates).
response->SetHeaderByName("HeaderA", "ValueANew", true);
expectedHeaders.clear();
expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
response->GetHeaderMap(headers);
TestMapEqual(expectedHeaders, headers, false);
}