diff --git a/BUILD.gn b/BUILD.gn index 7fe17a182..b92ad2ee9 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -614,6 +614,7 @@ static_library("libcef_static") { "//pdf", "//skia", "//storage/browser", + "//third_party/brotli", "//third_party/cld", "//third_party/hunspell", "//third_party/leveldatabase", diff --git a/libcef/browser/net/chrome_scheme_handler.cc b/libcef/browser/net/chrome_scheme_handler.cc index 6c44647ff..8f7ece21b 100644 --- a/libcef/browser/net/chrome_scheme_handler.cc +++ b/libcef/browser/net/chrome_scheme_handler.cc @@ -281,6 +281,7 @@ class Delegate : public InternalHandlerDelegate { } else { action->mime_type = "text/html"; action->resource_id = IDR_ABOUT_UI_CREDITS_HTML; + action->encoding = Action::ENCODING_BROTLI; } return true; } diff --git a/libcef/browser/net/internal_scheme_handler.cc b/libcef/browser/net/internal_scheme_handler.cc index b23eac32e..a2b47abf5 100644 --- a/libcef/browser/net/internal_scheme_handler.cc +++ b/libcef/browser/net/internal_scheme_handler.cc @@ -14,6 +14,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" #include "net/base/mime_util.h" +#include "third_party/brotli/dec/decode.h" #include "ui/base/resource/resource_bundle.h" namespace scheme { @@ -28,7 +29,7 @@ base::FilePath FilePathFromASCII(const std::string& str) { #endif } -static std::string GetMimeType(const std::string& filename) { +std::string GetMimeType(const std::string& filename) { // Requests should not block on the disk! On POSIX this goes to disk. // http://code.google.com/p/chromium/issues/detail?id=59849 base::ThreadRestrictions::ScopedAllowIO allow_io; @@ -48,6 +49,24 @@ static std::string GetMimeType(const std::string& filename) { return "text/plain"; } +bool DecodeBrotli(const base::StringPiece& encoded, + std::string& decoded) { + size_t decoded_size; + + const uint8_t* encoded_response_buffer = + reinterpret_cast(encoded.data()); + if (!BrotliDecompressedSize(encoded.size(), encoded_response_buffer, + &decoded_size)) { + return false; + } + + decoded.resize(decoded_size); + return BrotliDecompressBuffer(encoded.size(), encoded_response_buffer, + &decoded_size, + reinterpret_cast(&decoded[0])) == + BROTLI_RESULT_SUCCESS; +} + class RedirectHandler : public CefResourceHandler { public: explicit RedirectHandler(const GURL& url) @@ -153,6 +172,16 @@ class InternalHandlerFactory : public CefSchemeHandlerFactory { base::StringPiece piece = CefContentClient::Get()->GetDataResource( action.resource_id, ui::SCALE_FACTOR_NONE); if (!piece.empty()) { + std::string decoded; + if (action.encoding == + InternalHandlerDelegate::Action::ENCODING_BROTLI && + !DecodeBrotli(piece, decoded)) { + decoded = "Unable to decode content!"; + } + + if (!decoded.empty()) + piece = base::StringPiece(decoded); + action.stream = CefStreamReader::CreateForData(const_cast(piece.data()), piece.size()); @@ -183,7 +212,8 @@ class InternalHandlerFactory : public CefSchemeHandlerFactory { InternalHandlerDelegate::Action::Action() : stream_size(-1), - resource_id(-1) { + resource_id(-1), + encoding(ENCODING_NONE) { } CefRefPtr CreateInternalHandlerFactory( diff --git a/libcef/browser/net/internal_scheme_handler.h b/libcef/browser/net/internal_scheme_handler.h index bd1c17b52..7c95d65d2 100644 --- a/libcef/browser/net/internal_scheme_handler.h +++ b/libcef/browser/net/internal_scheme_handler.h @@ -28,8 +28,13 @@ class InternalHandlerDelegate { CefRefPtr stream; int stream_size; - // Option 2: Specify a resource id to load static content. + // Option 2: Specify a resource id to load static content. May include an + // optional encoding type. int resource_id; + enum Encoding { + ENCODING_NONE, + ENCODING_BROTLI, + } encoding; // Option 3: Redirect to the specified URL. GURL redirect_url;