blob: 3e6fae403e8609949a6103a2773d6fe687ef72b0 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/public/cpp/web_sandbox_flags.h"
#include <set>
#include <vector>
#include "base/containers/fixed_flat_map.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom.h"
namespace network {
using mojom::WebSandboxFlags;
namespace {
// See: https://infra.spec.whatwg.org/#ascii-whitespace
// This is different from: base::kWhitespaceASCII.
const char* kHtmlWhitespace = " \n\t\r\f";
WebSandboxFlags ParseWebSandboxToken(std::string_view token) {
using enum WebSandboxFlags;
static constexpr auto kTokenToWebSandboxFlags =
base::MakeFixedFlatMap<std::string_view, WebSandboxFlags>({
{"allow-downloads", kDownloads},
{"allow-forms", kForms},
{"allow-modals", kModals},
{"allow-orientation-lock", kOrientationLock},
{"allow-pointer-lock", kPointerLock},
{"allow-popups", kPopups | kTopNavigationToCustomProtocols},
{"allow-popups-to-escape-sandbox",
kPropagatesToAuxiliaryBrowsingContexts},
{"allow-presentation", kPresentationController},
{"allow-same-origin", kOrigin},
{"allow-scripts", kAutomaticFeatures | kScripts},
{"allow-storage-access-by-user-activation",
kStorageAccessByUserActivation},
{"allow-top-navigation",
kTopNavigation | kTopNavigationToCustomProtocols},
{"allow-top-navigation-by-user-activation",
kTopNavigationByUserActivation},
{"allow-top-navigation-to-custom-protocols",
kTopNavigationToCustomProtocols},
{"allow-same-site-none-cookies", kAllowSameSiteNoneCookies},
});
std::string lowered_token = base::ToLowerASCII(token);
const auto it = kTokenToWebSandboxFlags.find(lowered_token);
return it == kTokenToWebSandboxFlags.end() ? kNone : it->second;
}
} // namespace
// See: http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
WebSandboxFlagsParsingResult ParseWebSandboxPolicy(
std::string_view input,
WebSandboxFlags ignored_flags) {
WebSandboxFlagsParsingResult out;
out.flags = WebSandboxFlags::kAll;
std::vector<std::string_view> error_tokens;
for (const auto& token :
base::SplitStringPiece(input, kHtmlWhitespace, base::KEEP_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)) {
WebSandboxFlags flags = ~ParseWebSandboxToken(token);
flags |= ignored_flags;
out.flags &= flags;
if (flags == WebSandboxFlags::kAll)
error_tokens.push_back(token);
}
if (!error_tokens.empty()) {
// Some tests expect the order of error tokens to be preserved, while
// removing the duplicates:
// See /fast/frames/sandboxed-iframe-attribute-parsing-03.html
std::set<std::string_view> set;
std::erase_if(error_tokens, [&](auto x) { return !set.insert(x).second; });
out.error_message =
"'" + base::JoinString(error_tokens, "', '") +
(error_tokens.size() > 1 ? "' are invalid sandbox flags."
: "' is an invalid sandbox flag.");
}
return out;
}
} // namespace network