Index: webkit/browser/appcache/manifest_parser.cc |
diff --git a/webkit/browser/appcache/manifest_parser.cc b/webkit/browser/appcache/manifest_parser.cc |
deleted file mode 100644 |
index f43d8890312f6991a9f7b571fc63531386a99ebe..0000000000000000000000000000000000000000 |
--- a/webkit/browser/appcache/manifest_parser.cc |
+++ /dev/null |
@@ -1,381 +0,0 @@ |
-// Copyright (c) 2011 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. |
-// |
-// This is a port of ManifestParser.cc from WebKit/WebCore/loader/appcache. |
- |
-/* |
- * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * |
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "webkit/browser/appcache/manifest_parser.h" |
- |
-#include "base/command_line.h" |
-#include "base/i18n/icu_string_conversions.h" |
-#include "base/logging.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "url/gurl.h" |
- |
-namespace appcache { |
- |
-namespace { |
- |
-// Helper function used to identify 'isPattern' annotations. |
-bool HasPatternMatchingAnnotation(const wchar_t* line_p, |
- const wchar_t* line_end) { |
- // Skip whitespace separating the resource url from the annotation. |
- // Note: trailing whitespace has already been trimmed from the line. |
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' ')) |
- ++line_p; |
- if (line_p == line_end) |
- return false; |
- std::wstring annotation(line_p, line_end - line_p); |
- return annotation == L"isPattern"; |
-} |
- |
-} |
- |
-enum Mode { |
- EXPLICIT, |
- INTERCEPT, |
- FALLBACK, |
- ONLINE_WHITELIST, |
- UNKNOWN_MODE, |
-}; |
- |
-enum InterceptVerb { |
- RETURN, |
- EXECUTE, |
- UNKNOWN_VERB, |
-}; |
- |
-Manifest::Manifest() |
- : online_whitelist_all(false), |
- did_ignore_intercept_namespaces(false) { |
-} |
- |
-Manifest::~Manifest() {} |
- |
-bool ParseManifest(const GURL& manifest_url, const char* data, int length, |
- ParseMode parse_mode, Manifest& manifest) { |
- // This is an implementation of the parsing algorithm specified in |
- // the HTML5 offline web application docs: |
- // http://www.w3.org/TR/html5/offline.html |
- // Do not modify it without consulting those docs. |
- // Though you might be tempted to convert these wstrings to UTF-8 or |
- // base::string16, this implementation seems simpler given the constraints. |
- |
- const wchar_t kSignature[] = L"CACHE MANIFEST"; |
- const size_t kSignatureLength = arraysize(kSignature) - 1; |
- const wchar_t kChromiumSignature[] = L"CHROMIUM CACHE MANIFEST"; |
- const size_t kChromiumSignatureLength = arraysize(kChromiumSignature) - 1; |
- |
- DCHECK(manifest.explicit_urls.empty()); |
- DCHECK(manifest.fallback_namespaces.empty()); |
- DCHECK(manifest.online_whitelist_namespaces.empty()); |
- DCHECK(!manifest.online_whitelist_all); |
- DCHECK(!manifest.did_ignore_intercept_namespaces); |
- |
- Mode mode = EXPLICIT; |
- |
- std::wstring data_string; |
- // TODO(jennb): cannot do UTF8ToWide(data, length, &data_string); |
- // until UTF8ToWide uses 0xFFFD Unicode replacement character. |
- base::CodepageToWide(std::string(data, length), base::kCodepageUTF8, |
- base::OnStringConversionError::SUBSTITUTE, &data_string); |
- const wchar_t* p = data_string.c_str(); |
- const wchar_t* end = p + data_string.length(); |
- |
- // Look for the magic signature: "^\xFEFF?CACHE MANIFEST[ \t]?" |
- // Example: "CACHE MANIFEST #comment" is a valid signature. |
- // Example: "CACHE MANIFEST;V2" is not. |
- |
- // When the input data starts with a UTF-8 Byte-Order-Mark |
- // (0xEF, 0xBB, 0xBF), the UTF8ToWide() function converts it to a |
- // Unicode BOM (U+FEFF). Skip a converted Unicode BOM if it exists. |
- int bom_offset = 0; |
- if (!data_string.empty() && data_string[0] == 0xFEFF) { |
- bom_offset = 1; |
- ++p; |
- } |
- |
- if (p >= end) |
- return false; |
- |
- // Check for a supported signature and skip p past it. |
- if (0 == data_string.compare(bom_offset, kSignatureLength, |
- kSignature)) { |
- p += kSignatureLength; |
- } else if (0 == data_string.compare(bom_offset, kChromiumSignatureLength, |
- kChromiumSignature)) { |
- p += kChromiumSignatureLength; |
- } else { |
- return false; |
- } |
- |
- // Character after "CACHE MANIFEST" must be whitespace. |
- if (p < end && *p != ' ' && *p != '\t' && *p != '\n' && *p != '\r') |
- return false; |
- |
- // Skip to the end of the line. |
- while (p < end && *p != '\r' && *p != '\n') |
- ++p; |
- |
- while (1) { |
- // Skip whitespace |
- while (p < end && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t')) |
- ++p; |
- |
- if (p == end) |
- break; |
- |
- const wchar_t* line_start = p; |
- |
- // Find the end of the line |
- while (p < end && *p != '\r' && *p != '\n') |
- ++p; |
- |
- // Check if we have a comment |
- if (*line_start == '#') |
- continue; |
- |
- // Get rid of trailing whitespace |
- const wchar_t* tmp = p - 1; |
- while (tmp > line_start && (*tmp == ' ' || *tmp == '\t')) |
- --tmp; |
- |
- std::wstring line(line_start, tmp - line_start + 1); |
- |
- if (line == L"CACHE:") { |
- mode = EXPLICIT; |
- } else if (line == L"FALLBACK:") { |
- mode = FALLBACK; |
- } else if (line == L"NETWORK:") { |
- mode = ONLINE_WHITELIST; |
- } else if (line == L"CHROMIUM-INTERCEPT:") { |
- mode = INTERCEPT; |
- } else if (*(line.end() - 1) == ':') { |
- mode = UNKNOWN_MODE; |
- } else if (mode == UNKNOWN_MODE) { |
- continue; |
- } else if (line == L"*" && mode == ONLINE_WHITELIST) { |
- manifest.online_whitelist_all = true; |
- continue; |
- } else if (mode == EXPLICIT || mode == ONLINE_WHITELIST) { |
- const wchar_t *line_p = line.c_str(); |
- const wchar_t *line_end = line_p + line.length(); |
- |
- // Look for whitespace separating the URL from subsequent ignored tokens. |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- base::string16 url16; |
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &url16); |
- GURL url = manifest_url.Resolve(url16); |
- if (!url.is_valid()) |
- continue; |
- if (url.has_ref()) { |
- GURL::Replacements replacements; |
- replacements.ClearRef(); |
- url = url.ReplaceComponents(replacements); |
- } |
- |
- // Scheme component must be the same as the manifest URL's. |
- if (url.scheme() != manifest_url.scheme()) { |
- continue; |
- } |
- |
- // See http://code.google.com/p/chromium/issues/detail?id=69594 |
- // We willfully violate the HTML5 spec at this point in order |
- // to support the appcaching of cross-origin HTTPS resources. |
- // Per the spec, EXPLICIT cross-origin HTTS resources should be |
- // ignored here. We've opted for a milder constraint and allow |
- // caching unless the resource has a "no-store" header. That |
- // condition is enforced in AppCacheUpdateJob. |
- |
- if (mode == EXPLICIT) { |
- manifest.explicit_urls.insert(url.spec()); |
- } else { |
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end); |
- manifest.online_whitelist_namespaces.push_back( |
- Namespace(APPCACHE_NETWORK_NAMESPACE, url, GURL(), is_pattern)); |
- } |
- } else if (mode == INTERCEPT) { |
- if (parse_mode != PARSE_MANIFEST_ALLOWING_INTERCEPTS) { |
- manifest.did_ignore_intercept_namespaces = true; |
- continue; |
- } |
- |
- // Lines of the form, |
- // <urlnamespace> <intercept_type> <targeturl> |
- const wchar_t* line_p = line.c_str(); |
- const wchar_t* line_end = line_p + line.length(); |
- |
- // Look for first whitespace separating the url namespace from |
- // the intercept type. |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- if (line_p == line_end) |
- continue; // There was no whitespace separating the URLs. |
- |
- base::string16 namespace_url16; |
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16); |
- GURL namespace_url = manifest_url.Resolve(namespace_url16); |
- if (!namespace_url.is_valid()) |
- continue; |
- if (namespace_url.has_ref()) { |
- GURL::Replacements replacements; |
- replacements.ClearRef(); |
- namespace_url = namespace_url.ReplaceComponents(replacements); |
- } |
- |
- // The namespace URL must have the same scheme, host and port |
- // as the manifest's URL. |
- if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) |
- continue; |
- |
- // Skip whitespace separating namespace from the type. |
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' ')) |
- ++line_p; |
- |
- // Look for whitespace separating the type from the target url. |
- const wchar_t* type_start = line_p; |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- // Look for a type value we understand, otherwise skip the line. |
- InterceptVerb verb = UNKNOWN_VERB; |
- std::wstring type(type_start, line_p - type_start); |
- if (type == L"return") { |
- verb = RETURN; |
- } else if (type == L"execute" && |
- CommandLine::ForCurrentProcess()->HasSwitch( |
- kEnableExecutableHandlers)) { |
- verb = EXECUTE; |
- } |
- if (verb == UNKNOWN_VERB) |
- continue; |
- |
- // Skip whitespace separating type from the target_url. |
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' ')) |
- ++line_p; |
- |
- // Look for whitespace separating the URL from subsequent ignored tokens. |
- const wchar_t* target_url_start = line_p; |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- base::string16 target_url16; |
- base::WideToUTF16(target_url_start, line_p - target_url_start, |
- &target_url16); |
- GURL target_url = manifest_url.Resolve(target_url16); |
- if (!target_url.is_valid()) |
- continue; |
- |
- if (target_url.has_ref()) { |
- GURL::Replacements replacements; |
- replacements.ClearRef(); |
- target_url = target_url.ReplaceComponents(replacements); |
- } |
- if (manifest_url.GetOrigin() != target_url.GetOrigin()) |
- continue; |
- |
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end); |
- manifest.intercept_namespaces.push_back( |
- Namespace(APPCACHE_INTERCEPT_NAMESPACE, namespace_url, |
- target_url, is_pattern, verb == EXECUTE)); |
- } else if (mode == FALLBACK) { |
- const wchar_t* line_p = line.c_str(); |
- const wchar_t* line_end = line_p + line.length(); |
- |
- // Look for whitespace separating the two URLs |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- if (line_p == line_end) { |
- // There was no whitespace separating the URLs. |
- continue; |
- } |
- |
- base::string16 namespace_url16; |
- base::WideToUTF16(line.c_str(), line_p - line.c_str(), &namespace_url16); |
- GURL namespace_url = manifest_url.Resolve(namespace_url16); |
- if (!namespace_url.is_valid()) |
- continue; |
- if (namespace_url.has_ref()) { |
- GURL::Replacements replacements; |
- replacements.ClearRef(); |
- namespace_url = namespace_url.ReplaceComponents(replacements); |
- } |
- |
- // Fallback namespace URL must have the same scheme, host and port |
- // as the manifest's URL. |
- if (manifest_url.GetOrigin() != namespace_url.GetOrigin()) { |
- continue; |
- } |
- |
- // Skip whitespace separating fallback namespace from URL. |
- while (line_p < line_end && (*line_p == '\t' || *line_p == ' ')) |
- ++line_p; |
- |
- // Look for whitespace separating the URL from subsequent ignored tokens. |
- const wchar_t* fallback_start = line_p; |
- while (line_p < line_end && *line_p != '\t' && *line_p != ' ') |
- ++line_p; |
- |
- base::string16 fallback_url16; |
- base::WideToUTF16(fallback_start, line_p - fallback_start, |
- &fallback_url16); |
- GURL fallback_url = manifest_url.Resolve(fallback_url16); |
- if (!fallback_url.is_valid()) |
- continue; |
- if (fallback_url.has_ref()) { |
- GURL::Replacements replacements; |
- replacements.ClearRef(); |
- fallback_url = fallback_url.ReplaceComponents(replacements); |
- } |
- |
- // Fallback entry URL must have the same scheme, host and port |
- // as the manifest's URL. |
- if (manifest_url.GetOrigin() != fallback_url.GetOrigin()) { |
- continue; |
- } |
- |
- bool is_pattern = HasPatternMatchingAnnotation(line_p, line_end); |
- |
- // Store regardless of duplicate namespace URL. Only first match |
- // will ever be used. |
- manifest.fallback_namespaces.push_back( |
- Namespace(APPCACHE_FALLBACK_NAMESPACE, namespace_url, |
- fallback_url, is_pattern)); |
- } else { |
- NOTREACHED(); |
- } |
- } |
- |
- return true; |
-} |
- |
-} // namespace appcache |