Home | History | Annotate | Download | only in plugin
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ppapi/native_client/src/trusted/plugin/nacl_http_response_headers.h"
      6 
      7 #include <algorithm>
      8 #include <sstream>
      9 
     10 namespace {
     11 
     12 // TODO(jvoung): Use Tokenize from base/strings/string_util.h when this moves
     13 // to Chromium.
     14 void SplitString(const std::string& str,
     15                  char delim,
     16                  std::vector<std::string>* elems) {
     17   std::stringstream ss(str);
     18   std::string item;
     19   while (std::getline(ss, item, delim)) {
     20     elems->push_back(item);
     21   }
     22 }
     23 
     24 bool SplitOnce(const std::string& str,
     25                char delim,
     26                std::vector<std::string>* elems) {
     27   size_t pos = str.find(delim);
     28   if (pos != std::string::npos) {
     29     elems->push_back(str.substr(0, pos));
     30     elems->push_back(str.substr(pos + 1));
     31     return true;
     32   }
     33   return false;
     34 }
     35 
     36 }  // namespace
     37 
     38 namespace plugin {
     39 
     40 NaClHttpResponseHeaders::NaClHttpResponseHeaders() {}
     41 
     42 NaClHttpResponseHeaders::~NaClHttpResponseHeaders() {}
     43 
     44 void NaClHttpResponseHeaders::Parse(const std::string& headers_str) {
     45   // PPAPI response headers are \n delimited. Separate out the lines.
     46   std::vector<std::string> lines;
     47   SplitString(headers_str, '\n', &lines);
     48 
     49   for (size_t i = 0; i < lines.size(); ++i) {
     50     std::vector<std::string> tokens;
     51     // Split along the key-value pair separator char.
     52     if (!SplitOnce(lines[i], ':', &tokens)) {
     53       // Ignore funny header lines that don't have the key-value separator.
     54       continue;
     55     }
     56     std::string key = tokens[0];
     57     // Also ignore keys that start with white-space (they are invalid).
     58     // See: HttpResponseHeadersTest.NormalizeHeadersLeadingWhitespace.
     59     if (key[0] == ' ' || key[0] == '\t')
     60       continue;
     61     // TODO(jvoung): replace some of this with TrimWhitespaceASCII when
     62     // we move code to chromium.
     63     // Strip trailing whitespace from the key to normalize.
     64     size_t pos = key.find_last_not_of(" \t");
     65     if (pos != std::string::npos)
     66       key.erase(pos + 1);
     67     // Strip leading whitespace from the value to normalize.
     68     std::string value = tokens[1];
     69     value.erase(0, value.find_first_not_of(" \t"));
     70     header_entries_.push_back(Entry(key, value));
     71   }
     72 }
     73 
     74 std::string NaClHttpResponseHeaders::GetHeader(const std::string& name) {
     75   for (size_t i = 0; i < header_entries_.size(); ++i) {
     76     const Entry& entry = header_entries_[i];
     77     std::string key = entry.first;
     78     // TODO(jvoung): replace with LowerCaseEqualsASCII later.
     79     std::transform(key.begin(), key.end(), key.begin(), ::tolower);
     80     if (key.compare(name) == 0)
     81       return entry.second;
     82   }
     83   return std::string();
     84 }
     85 
     86 std::string NaClHttpResponseHeaders::GetCacheValidators() {
     87   std::string result = GetHeader("etag");
     88   if (!result.empty())
     89     result = "etag:" + result;
     90   std::string lm = GetHeader("last-modified");
     91   if (!lm.empty()) {
     92     if (!result.empty())
     93       result += "&";
     94     result += "last-modified:" + lm;
     95   }
     96   return result;
     97 }
     98 
     99 bool NaClHttpResponseHeaders::CacheControlNoStore() {
    100   for (size_t i = 0; i < header_entries_.size(); ++i) {
    101     const Entry& entry = header_entries_[i];
    102     std::string key = entry.first;
    103     // TODO(jvoung): replace with LowerCaseEqualsASCII later.
    104     std::transform(key.begin(), key.end(), key.begin(), ::tolower);
    105     if (key.compare("cache-control") == 0) {
    106       std::string cc = entry.second;
    107       std::transform(cc.begin(), cc.end(), cc.begin(), ::tolower);
    108       if (entry.second.find("no-store") != std::string::npos)
    109         return true;
    110     }
    111   }
    112   return false;
    113 }
    114 
    115 }  // namespace plugin
    116