Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1886)

Unified Diff: content/browser/service_worker/link_header_support.cc

Issue 1811163002: Share link header parsing code between blink and content. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@base-optional
Patch Set: rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/DEPS ('k') | content/browser/service_worker/link_header_support_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/service_worker/link_header_support.cc
diff --git a/content/browser/service_worker/link_header_support.cc b/content/browser/service_worker/link_header_support.cc
index 1a957c7269306821cd55784d329ecb8cdbd6274f..4f46dfcac0dceb8c155da2ea439ad3f8f83ee429 100644
--- a/content/browser/service_worker/link_header_support.cc
+++ b/content/browser/service_worker/link_header_support.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "components/link_header_util/link_header_util.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/loader/resource_request_info_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
@@ -23,147 +24,6 @@ namespace content {
namespace {
-// A variation of base::StringTokenizer and net::HttpUtil::ValuesIterator.
-// Takes the parsing of StringTokenizer and adds support for quoted strings that
-// are quoted by matching <> (and does not support escaping in those strings).
-// Also has the behavior of ValuesIterator where it strips whitespace from all
-// values and only outputs non-empty values.
-// Only supports ',' as separator and supports '' "" and <> as quote chars.
-// TODO(mek): Figure out if there is a way to share this with the parsing code
-// in blink::LinkHeader.
-class ValueTokenizer {
- public:
- ValueTokenizer(std::string::const_iterator begin,
- std::string::const_iterator end)
- : token_begin_(begin), token_end_(begin), end_(end) {}
-
- std::string::const_iterator token_begin() const { return token_begin_; }
- std::string::const_iterator token_end() const { return token_end_; }
-
- bool GetNext() {
- while (GetNextInternal()) {
- net::HttpUtil::TrimLWS(&token_begin_, &token_end_);
-
- // Only return non-empty values.
- if (token_begin_ != token_end_)
- return true;
- }
- return false;
- }
-
- private:
- // Updates token_begin_ and token_end_ to point to the (possibly empty) next
- // token. Returns false if end-of-string was reached first.
- bool GetNextInternal() {
- // First time this is called token_end_ points to the first character in the
- // input. Every other time token_end_ points to the delimiter at the end of
- // the last returned token (which could be the end of the string).
-
- // End of string, return false.
- if (token_end_ == end_)
- return false;
-
- // Skip past the delimiter.
- if (*token_end_ == ',')
- ++token_end_;
-
- // Make token_begin_ point to the beginning of the next token, and search
- // for the end of the token in token_end_.
- token_begin_ = token_end_;
-
- // Set to true if we're currently inside a quoted string.
- bool in_quote = false;
- // Set to true if we're currently inside a quoted string, and have just
- // encountered an escape character. In this case a closing quote will be
- // ignored.
- bool in_escape = false;
- // If currently in a quoted string, this is the character that (when not
- // escaped) indicates the end of the string.
- char quote_close_char = '\0';
- // If currently in a quoted string, this is set to true if it is possible to
- // escape the closing quote using '\'.
- bool quote_allows_escape = false;
-
- while (token_end_ != end_) {
- char c = *token_end_;
- if (in_quote) {
- if (in_escape) {
- in_escape = false;
- } else if (quote_allows_escape && c == '\\') {
- in_escape = true;
- } else if (c == quote_close_char) {
- in_quote = false;
- }
- } else {
- if (c == ',')
- break;
- if (c == '\'' || c == '"' || c == '<') {
- in_quote = true;
- quote_close_char = (c == '<' ? '>' : c);
- quote_allows_escape = (c != '<');
- }
- }
- ++token_end_;
- }
- return true;
- }
-
- std::string::const_iterator token_begin_;
- std::string::const_iterator token_end_;
- std::string::const_iterator end_;
-};
-
-// Parses one link in a link header into its url and parameters.
-// A link is of the form "<some-url>; param1=value1; param2=value2".
-// Returns false if parsing the link failed, returns true on success. This
-// method is more lenient than the RFC. It doesn't fail on things like invalid
-// characters in the URL, and also doesn't verify that certain parameters should
-// or shouldn't be quoted strings.
-// If a parameter occurs more than once in the link, only the first value is
-// returned in params as this is the required behavior for all attributes chrome
-// currently cares about in link headers.
-bool ParseLink(std::string::const_iterator begin,
- std::string::const_iterator end,
- std::string* url,
- std::unordered_map<std::string, std::string>* params) {
- // Can't parse an empty string.
- if (begin == end)
- return false;
-
- // Extract the URL part (everything between '<' and first '>' character).
- if (*begin != '<')
- return false;
- ++begin;
- std::string::const_iterator url_begin = begin;
- std::string::const_iterator url_end = std::find(begin, end, '>');
- // Fail if we did not find a '>'.
- if (url_end == end)
- return false;
- begin = url_end;
- net::HttpUtil::TrimLWS(&url_begin, &url_end);
- *url = std::string(url_begin, url_end);
-
- // Skip the '>' at the end of the URL, trim any remaining whitespace, and make
- // sure it is followed by a ';' to indicate the start of parameters.
- ++begin;
- net::HttpUtil::TrimLWS(&begin, &end);
- if (begin != end && *begin != ';')
- return false;
-
- // Parse all the parameters.
- net::HttpUtil::NameValuePairsIterator params_iterator(
- begin, end, ';', net::HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL);
- while (params_iterator.GetNext()) {
- if (!net::HttpUtil::IsToken(params_iterator.name_begin(),
- params_iterator.name_end()))
- return false;
- std::string name = base::ToLowerASCII(base::StringPiece(
- params_iterator.name_begin(), params_iterator.name_end()));
- params->insert(std::make_pair(name, params_iterator.value()));
- }
- return params_iterator.valid();
-}
-
void RegisterServiceWorkerFinished(int64_t trace_id, bool result) {
TRACE_EVENT_ASYNC_END1("ServiceWorker",
"LinkHeaderResourceThrottle::HandleServiceWorkerLink",
@@ -173,7 +33,7 @@ void RegisterServiceWorkerFinished(int64_t trace_id, bool result) {
void HandleServiceWorkerLink(
const net::URLRequest* request,
const std::string& url,
- const std::unordered_map<std::string, std::string>& params,
+ const std::unordered_map<std::string, base::Optional<std::string>>& params,
ServiceWorkerContextWrapper* service_worker_context_for_testing) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -215,7 +75,7 @@ void HandleServiceWorkerLink(
auto scope_param = params.find("scope");
GURL scope_url = scope_param == params.end()
? script_url.Resolve("./")
- : context_url.Resolve(scope_param->second);
+ : context_url.Resolve(scope_param->second.value_or(""));
if (!context_url.is_valid() || !script_url.is_valid() ||
!scope_url.is_valid())
@@ -255,13 +115,17 @@ void ProcessLinkHeaderValueForRequest(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::string url;
- std::unordered_map<std::string, std::string> params;
- if (!ParseLink(value_begin, value_end, &url, &params))
+ std::unordered_map<std::string, base::Optional<std::string>> params;
+ if (!link_header_util::ParseLinkHeaderValue(value_begin, value_end, &url,
+ &params))
return;
- for (const auto& rel :
- base::SplitStringPiece(params["rel"], HTTP_LWS, base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
+ auto rel_param = params.find("rel");
+ if (rel_param == params.end() || !rel_param->second)
+ return;
+ for (const auto& rel : base::SplitStringPiece(rel_param->second.value(),
+ HTTP_LWS, base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
if (base::EqualsCaseInsensitiveASCII(rel, "serviceworker"))
HandleServiceWorkerLink(request, url, params,
service_worker_context_for_testing);
@@ -283,29 +147,10 @@ void ProcessLinkHeaderForRequest(
const net::URLRequest* request,
const std::string& link_header,
ServiceWorkerContextWrapper* service_worker_context_for_testing) {
- ValueTokenizer tokenizer(link_header.begin(), link_header.end());
- while (tokenizer.GetNext()) {
- ProcessLinkHeaderValueForRequest(request, tokenizer.token_begin(),
- tokenizer.token_end(),
+ for (const auto& value : link_header_util::SplitLinkHeader(link_header)) {
+ ProcessLinkHeaderValueForRequest(request, value.first, value.second,
service_worker_context_for_testing);
}
}
-void SplitLinkHeaderForTesting(const std::string& header,
- std::vector<std::string>* values) {
- values->clear();
- ValueTokenizer tokenizer(header.begin(), header.end());
- while (tokenizer.GetNext()) {
- values->push_back(
- std::string(tokenizer.token_begin(), tokenizer.token_end()));
- }
-}
-
-bool ParseLinkHeaderValueForTesting(
- const std::string& link,
- std::string* url,
- std::unordered_map<std::string, std::string>* params) {
- return ParseLink(link.begin(), link.end(), url, params);
-}
-
} // namespace content
« no previous file with comments | « content/browser/DEPS ('k') | content/browser/service_worker/link_header_support_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698