[data URI] Do not remove whitespace on non-base64 encoded content
Catch up with a Gecko change from a few years ago.
af910097a3
removed the mime-type check on data URLs.
This was the cause of wpt/xhr/data-uri.htm failing only on Chrome.
An Enterprise Policy as a safe measure has been added as protection.
Bug: 40487190, 40540384
Change-Id: Ia6a4f6b4c140cc8dd5bf4c5f52604f1c29408c1f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5783226
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Reviewed-by: mmenke <mmenke@chromium.org>
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Greg Thompson <grt@chromium.org>
Reviewed-by: Yann Dago <ydago@chromium.org>
Reviewed-by: Sébastien Lalancette <seblalancette@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1352747}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
8a5bc8d055
commit
34b6c2b36e
chrome
components/policy
resources
templates
test
data
pref_mapping
net/base
third_party/blink/web_tests
external
wpt
platform
mac-mac13
virtual
keepalive-in-browser-migration
external
wpt
fetch
data-urls
mac-mac14-arm64
virtual
keepalive-in-browser-migration
external
wpt
fetch
data-urls
mac-mac14
virtual
keepalive-in-browser-migration
external
wpt
fetch
data-urls
tools/metrics/histograms/metadata/enterprise
@@ -187,6 +187,7 @@
|
|||||||
#include "media/audio/audio_manager.h"
|
#include "media/audio/audio_manager.h"
|
||||||
#include "media/base/localized_strings.h"
|
#include "media/base/localized_strings.h"
|
||||||
#include "media/media_buildflags.h"
|
#include "media/media_buildflags.h"
|
||||||
|
#include "net/base/data_url.h"
|
||||||
#include "net/base/net_module.h"
|
#include "net/base/net_module.h"
|
||||||
#include "net/cookies/cookie_monster.h"
|
#include "net/cookies/cookie_monster.h"
|
||||||
#include "net/http/http_network_layer.h"
|
#include "net/http/http_network_layer.h"
|
||||||
@@ -1179,6 +1180,14 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
|
|||||||
// IsolateOrigins policy is taken care of through SiteIsolationPrefsObserver
|
// IsolateOrigins policy is taken care of through SiteIsolationPrefsObserver
|
||||||
// (constructed and owned by BrowserProcessImpl).
|
// (constructed and owned by BrowserProcessImpl).
|
||||||
|
|
||||||
|
// We need to set the policy for data URLs since they can be created in
|
||||||
|
// any process. The ChromeContentBrowserClient will take care of child
|
||||||
|
// processes.
|
||||||
|
if (!local_state->GetBoolean(prefs::kDataURLWhitespacePreservationEnabled) &&
|
||||||
|
!command_line->HasSwitch(net::kRemoveWhitespaceForDataURLs)) {
|
||||||
|
command_line->AppendSwitch(net::kRemoveWhitespaceForDataURLs);
|
||||||
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(IS_ANDROID)
|
#if BUILDFLAG(IS_ANDROID)
|
||||||
// The admin should also be able to use these policies to force Site Isolation
|
// The admin should also be able to use these policies to force Site Isolation
|
||||||
// off (on Android; using enterprise policies to disable Site Isolation is not
|
// off (on Android; using enterprise policies to disable Site Isolation is not
|
||||||
|
@@ -370,6 +370,7 @@
|
|||||||
#include "media/media_buildflags.h"
|
#include "media/media_buildflags.h"
|
||||||
#include "media/mojo/buildflags.h"
|
#include "media/mojo/buildflags.h"
|
||||||
#include "mojo/public/cpp/bindings/remote.h"
|
#include "mojo/public/cpp/bindings/remote.h"
|
||||||
|
#include "net/base/data_url.h"
|
||||||
#include "net/base/features.h"
|
#include "net/base/features.h"
|
||||||
#include "net/cookies/site_for_cookies.h"
|
#include "net/cookies/site_for_cookies.h"
|
||||||
#include "net/ssl/client_cert_store.h"
|
#include "net/ssl/client_cert_store.h"
|
||||||
@@ -1596,6 +1597,8 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs(
|
|||||||
registry->RegisterBooleanPref(prefs::kSitePerProcess, false);
|
registry->RegisterBooleanPref(prefs::kSitePerProcess, false);
|
||||||
registry->RegisterBooleanPref(prefs::kTabFreezingEnabled, true);
|
registry->RegisterBooleanPref(prefs::kTabFreezingEnabled, true);
|
||||||
registry->RegisterIntegerPref(prefs::kSCTAuditingHashdanceReportCount, 0);
|
registry->RegisterIntegerPref(prefs::kSCTAuditingHashdanceReportCount, 0);
|
||||||
|
registry->RegisterBooleanPref(prefs::kDataURLWhitespacePreservationEnabled,
|
||||||
|
true);
|
||||||
#if BUILDFLAG(IS_CHROMEOS)
|
#if BUILDFLAG(IS_CHROMEOS)
|
||||||
registry->RegisterBooleanPref(prefs::kNativeClientForceAllowed, false);
|
registry->RegisterBooleanPref(prefs::kNativeClientForceAllowed, false);
|
||||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||||
@@ -3104,6 +3107,13 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
|
|||||||
command_line, GetProfilerProcessType(*command_line),
|
command_line, GetProfilerProcessType(*command_line),
|
||||||
child_process_id);
|
child_process_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enterprise policies may set the local state. `g_browser_process` is only
|
||||||
|
// available for non-zygote processes.
|
||||||
|
if (!g_browser_process->local_state()->GetBoolean(
|
||||||
|
prefs::kDataURLWhitespacePreservationEnabled)) {
|
||||||
|
command_line->AppendSwitch(net::kRemoveWhitespaceForDataURLs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH)
|
||||||
|
@@ -264,6 +264,7 @@ source_set("policy_specific_browser_tests") {
|
|||||||
"test/autoplay_policy_browsertest.cc",
|
"test/autoplay_policy_browsertest.cc",
|
||||||
"test/bookmark_bar_enabled_browsertest.cc",
|
"test/bookmark_bar_enabled_browsertest.cc",
|
||||||
"test/component_updater_policy_browsertest.cc",
|
"test/component_updater_policy_browsertest.cc",
|
||||||
|
"test/data_url_policy_browsertest.cc",
|
||||||
"test/developer_tools_policy_browsertest.cc",
|
"test/developer_tools_policy_browsertest.cc",
|
||||||
"test/download_directory_browsertest.cc",
|
"test/download_directory_browsertest.cc",
|
||||||
"test/ipv6_reachability_override_policy_browsertest.cc",
|
"test/ipv6_reachability_override_policy_browsertest.cc",
|
||||||
|
@@ -299,6 +299,9 @@ const PolicyToPreferenceMapEntry kSimplePolicyMap[] = {
|
|||||||
{ key::kComponentUpdatesEnabled,
|
{ key::kComponentUpdatesEnabled,
|
||||||
prefs::kComponentUpdatesEnabled,
|
prefs::kComponentUpdatesEnabled,
|
||||||
base::Value::Type::BOOLEAN },
|
base::Value::Type::BOOLEAN },
|
||||||
|
{ key::kDataURLWhitespacePreservationEnabled,
|
||||||
|
prefs::kDataURLWhitespacePreservationEnabled,
|
||||||
|
base::Value::Type::BOOLEAN },
|
||||||
{ key::kDefaultPopupsSetting,
|
{ key::kDefaultPopupsSetting,
|
||||||
prefs::kManagedDefaultPopupsSetting,
|
prefs::kManagedDefaultPopupsSetting,
|
||||||
base::Value::Type::INTEGER },
|
base::Value::Type::INTEGER },
|
||||||
|
97
chrome/browser/policy/test/data_url_policy_browsertest.cc
Normal file
97
chrome/browser/policy/test/data_url_policy_browsertest.cc
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// Copyright 2024 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "base/command_line.h"
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "chrome/browser/policy/policy_test_utils.h"
|
||||||
|
#include "chrome/browser/profiles/profile.h"
|
||||||
|
#include "chrome/browser/ui/browser.h"
|
||||||
|
#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
||||||
|
#include "chrome/test/base/ui_test_utils.h"
|
||||||
|
#include "components/policy/core/common/policy_map.h"
|
||||||
|
#include "components/policy/policy_constants.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "content/public/common/content_switches.h"
|
||||||
|
#include "content/public/test/browser_test.h"
|
||||||
|
#include "content/public/test/browser_test_utils.h"
|
||||||
|
#include "content/public/test/test_utils.h"
|
||||||
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace policy {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr char kGetDataURLResponse[] = R"(
|
||||||
|
(async () => {
|
||||||
|
function makeRequest(method, url) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
xhr.open(method, url);
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (this.status >= 200 && this.status < 300) {
|
||||||
|
resolve(xhr.responseText);
|
||||||
|
} else {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function () {
|
||||||
|
reject({
|
||||||
|
status: this.status,
|
||||||
|
statusText: xhr.statusText
|
||||||
|
});
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var result = await makeRequest("GET", "data:image/png,Hello, World!");
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
)";
|
||||||
|
|
||||||
|
class DataURLPolicyTest : public PolicyTest {
|
||||||
|
public:
|
||||||
|
DataURLPolicyTest() = default;
|
||||||
|
~DataURLPolicyTest() override = default;
|
||||||
|
|
||||||
|
// content::BrowserTestBase
|
||||||
|
void SetUpCommandLine(base::CommandLine* command_line) override {
|
||||||
|
content::IsolateAllSitesForTesting(command_line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
IN_PROC_BROWSER_TEST_F(DataURLPolicyTest, PolicyApplies) {
|
||||||
|
ASSERT_TRUE(embedded_test_server()->Start());
|
||||||
|
|
||||||
|
const GURL url(embedded_test_server()->GetURL("a.com", "/empty.html"));
|
||||||
|
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||||
|
|
||||||
|
// Check the default policy off.
|
||||||
|
auto* tab = browser()->tab_strip_model()->GetActiveWebContents();
|
||||||
|
EXPECT_EQ("Hello, World!", EvalJs(tab, kGetDataURLResponse));
|
||||||
|
|
||||||
|
PolicyMap policies;
|
||||||
|
SetPolicy(&policies, key::kDataURLWhitespacePreservationEnabled,
|
||||||
|
base::Value(false));
|
||||||
|
UpdateProviderPolicy(policies);
|
||||||
|
|
||||||
|
// Kill the renderer process. The policy will be set on
|
||||||
|
// relaunch.
|
||||||
|
content::RenderProcessHost* process =
|
||||||
|
tab->GetPrimaryMainFrame()->GetProcess();
|
||||||
|
content::RenderProcessHostWatcher crash_observer(
|
||||||
|
process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
|
||||||
|
process->Shutdown(-1);
|
||||||
|
crash_observer.Wait();
|
||||||
|
|
||||||
|
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||||
|
EXPECT_EQ("Hello,World!", EvalJs(tab, kGetDataURLResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
} // namespace policy
|
@@ -426,6 +426,10 @@ inline constexpr char kPromptForDownload[] = "download.prompt_for_download";
|
|||||||
// Controls if the QUIC protocol is allowed.
|
// Controls if the QUIC protocol is allowed.
|
||||||
inline constexpr char kQuicAllowed[] = "net.quic_allowed";
|
inline constexpr char kQuicAllowed[] = "net.quic_allowed";
|
||||||
|
|
||||||
|
// Prefs for keeping whitespace for data URLs.
|
||||||
|
inline constexpr char kDataURLWhitespacePreservationEnabled[] =
|
||||||
|
"net.keep_whitespace_data_urls";
|
||||||
|
|
||||||
// Prefs for persisting network qualities.
|
// Prefs for persisting network qualities.
|
||||||
inline constexpr char kNetworkQualities[] = "net.network_qualities";
|
inline constexpr char kNetworkQualities[] = "net.network_qualities";
|
||||||
|
|
||||||
|
@@ -1296,6 +1296,7 @@ policies:
|
|||||||
1295: HelpMeReadSettings
|
1295: HelpMeReadSettings
|
||||||
1296: GenAiDefaultSettings
|
1296: GenAiDefaultSettings
|
||||||
1297: KioskActiveWiFiCredentialsScopeChangeEnabled
|
1297: KioskActiveWiFiCredentialsScopeChangeEnabled
|
||||||
|
1298: DataURLWhitespacePreservationEnabled
|
||||||
|
|
||||||
atomic_groups:
|
atomic_groups:
|
||||||
1: Homepage
|
1: Homepage
|
||||||
|
32
components/policy/resources/templates/policy_definitions/Network/DataURLWhitespacePreservationEnabled.yaml
Normal file
32
components/policy/resources/templates/policy_definitions/Network/DataURLWhitespacePreservationEnabled.yaml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
caption: DataURL Whitespace Preservation for all media types
|
||||||
|
default: true
|
||||||
|
desc: |-
|
||||||
|
This policy provides a temporary opt-out for changes to how Chrome handles whitepsace in <ph name="DATA_URL_SCHEME">data</ph> URLS.
|
||||||
|
Previously, whitespace would be kept only if the top level media type was <ph name="TEXT_MEDIA_TYPE">text</ph> or contained the media type string <ph name="XML">xml</ph>.
|
||||||
|
Now, whitespace will be preserved in all data URLs, regardless of media type.
|
||||||
|
|
||||||
|
If this policy is left unset or is set to True, the new behavior is enabled.
|
||||||
|
|
||||||
|
When this policy is set to False, the old behavior is enabled.
|
||||||
|
example_value: false
|
||||||
|
features:
|
||||||
|
dynamic_refresh: false
|
||||||
|
per_profile: false
|
||||||
|
future_on:
|
||||||
|
- fuchsia
|
||||||
|
items:
|
||||||
|
- caption: Keep whitespace for all mime-types
|
||||||
|
value: true
|
||||||
|
- caption: Only keep whitespace for text and xml mime-types
|
||||||
|
value: false
|
||||||
|
owners:
|
||||||
|
- dtapuska@chromium.org
|
||||||
|
- file://net/cookies/OWNERS
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
|
supported_on:
|
||||||
|
- android:130-
|
||||||
|
- chrome_os:130-
|
||||||
|
- chrome.*:130-
|
||||||
|
tags: []
|
||||||
|
type: main
|
@@ -0,0 +1,21 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"os": [
|
||||||
|
"win",
|
||||||
|
"linux",
|
||||||
|
"mac",
|
||||||
|
"chromeos_ash",
|
||||||
|
"chromeos_lacros",
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"simple_policy_pref_mapping_test": {
|
||||||
|
"pref_name": "net.keep_whitespace_data_urls",
|
||||||
|
"pref_location": "local_state",
|
||||||
|
"default_value": true,
|
||||||
|
"values_to_test": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@@ -10,6 +10,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "base/base64.h"
|
#include "base/base64.h"
|
||||||
|
#include "base/command_line.h"
|
||||||
#include "base/ranges/algorithm.h"
|
#include "base/ranges/algorithm.h"
|
||||||
#include "base/strings/escape.h"
|
#include "base/strings/escape.h"
|
||||||
#include "base/strings/string_split.h"
|
#include "base/strings/string_split.h"
|
||||||
@@ -21,8 +22,21 @@
|
|||||||
#include "url/gurl.h"
|
#include "url/gurl.h"
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// Determine if we are in the deprecated mode of whitespace removal
|
||||||
|
// Enterprise policies can enable this command line flag to force
|
||||||
|
// the old (non-standard compliant) behavior.
|
||||||
|
bool HasRemoveWhitespaceCommandLineFlag() {
|
||||||
|
const base::CommandLine* command_line =
|
||||||
|
base::CommandLine::ForCurrentProcess();
|
||||||
|
if (!command_line) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return command_line->HasSwitch(kRemoveWhitespaceForDataURLs);
|
||||||
|
}
|
||||||
|
|
||||||
// https://infra.spec.whatwg.org/#ascii-whitespace, which is referenced by
|
// https://infra.spec.whatwg.org/#ascii-whitespace, which is referenced by
|
||||||
// https://infra.spec.whatwg.org/#forgiving-base64, does not include \v in the
|
// https://infra.spec.whatwg.org/#forgiving-base64, does not include \v in the
|
||||||
// set of ASCII whitespace characters the way Unicode does.
|
// set of ASCII whitespace characters the way Unicode does.
|
||||||
@@ -157,13 +171,20 @@ bool DataURL::Parse(const GURL& url,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Strip whitespace for non-text MIME types.
|
// `temp`'s storage needs to be outside feature check since `raw_body` is
|
||||||
|
// a string_view.
|
||||||
std::string temp;
|
std::string temp;
|
||||||
if (!(mime_type_value.compare(0, 5, "text/") == 0 ||
|
// Strip whitespace for non-text MIME types. This is controlled either by
|
||||||
mime_type_value.find("xml") != std::string::npos)) {
|
// the feature (finch kill switch) or an enterprise policy which sets the
|
||||||
temp = std::string(raw_body);
|
// command line flag.
|
||||||
std::erase_if(temp, base::IsAsciiWhitespace<char>);
|
if (!base::FeatureList::IsEnabled(features::kKeepWhitespaceForDataUrls) ||
|
||||||
raw_body = temp;
|
HasRemoveWhitespaceCommandLineFlag()) {
|
||||||
|
if (!(mime_type_value.compare(0, 5, "text/") == 0 ||
|
||||||
|
mime_type_value.find("xml") != std::string::npos)) {
|
||||||
|
temp = std::string(raw_body);
|
||||||
|
std::erase_if(temp, base::IsAsciiWhitespace<char>);
|
||||||
|
raw_body = temp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = base::UnescapeBinaryURLComponent(raw_body);
|
*data = base::UnescapeBinaryURLComponent(raw_body);
|
||||||
|
@@ -18,6 +18,12 @@ namespace net {
|
|||||||
|
|
||||||
class HttpResponseHeaders;
|
class HttpResponseHeaders;
|
||||||
|
|
||||||
|
// This command line switch provides a means to disable data URL whitespace
|
||||||
|
// kKeepWhitespaceForDataUrls feature flag. This is set part of an enterprise
|
||||||
|
// policy and is intended as a kill switch.
|
||||||
|
inline constexpr std::string_view kRemoveWhitespaceForDataURLs =
|
||||||
|
"remove-keep-whitespace-for-data-urls";
|
||||||
|
|
||||||
// See RFC 2397 for a complete description of the 'data' URL scheme.
|
// See RFC 2397 for a complete description of the 'data' URL scheme.
|
||||||
//
|
//
|
||||||
// Briefly, a 'data' URL has the form:
|
// Briefly, a 'data' URL has the form:
|
||||||
|
@@ -27,22 +27,36 @@ struct ParseTestData {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class DataURLTest : public testing::Test,
|
class DataURLTest
|
||||||
public ::testing::WithParamInterface<bool> {
|
: public testing::Test,
|
||||||
protected:
|
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
|
||||||
void SetUp() override {
|
public:
|
||||||
if (GetParam()) {
|
DataURLTest() {
|
||||||
feature_list_.InitAndEnableFeature(features::kOptimizeParsingDataUrls);
|
using FeatureList = std::vector<base::test::FeatureRef>;
|
||||||
} else {
|
FeatureList enabled_features;
|
||||||
feature_list_.InitAndDisableFeature(features::kOptimizeParsingDataUrls);
|
FeatureList disabled_features;
|
||||||
}
|
const auto feature_set = [&](bool flag_on) -> FeatureList& {
|
||||||
|
return flag_on ? enabled_features : disabled_features;
|
||||||
|
};
|
||||||
|
feature_set(OptimizedParsing())
|
||||||
|
.push_back(features::kOptimizeParsingDataUrls);
|
||||||
|
feature_set(KeepWhitespace())
|
||||||
|
.push_back(features::kKeepWhitespaceForDataUrls);
|
||||||
|
feature_list_.InitWithFeatures(enabled_features, disabled_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OptimizedParsing() const { return std::get<0>(GetParam()); }
|
||||||
|
bool KeepWhitespace() const { return std::get<1>(GetParam()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::test::ScopedFeatureList feature_list_;
|
base::test::ScopedFeatureList feature_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(DataURLTest, DataURLTest, testing::Bool());
|
INSTANTIATE_TEST_SUITE_P(DataURLTest,
|
||||||
|
DataURLTest,
|
||||||
|
testing::Combine(
|
||||||
|
/*optimize_parsing=*/testing::Bool(),
|
||||||
|
/*keep_whitespace=*/testing::Bool()));
|
||||||
|
|
||||||
TEST_P(DataURLTest, Parse) {
|
TEST_P(DataURLTest, Parse) {
|
||||||
const ParseTestData tests[] = {
|
const ParseTestData tests[] = {
|
||||||
@@ -89,10 +103,9 @@ TEST_P(DataURLTest, Parse) {
|
|||||||
// invalid base64 content
|
// invalid base64 content
|
||||||
{"data:;base64,aGVs_-_-", false, "", "", ""},
|
{"data:;base64,aGVs_-_-", false, "", "", ""},
|
||||||
|
|
||||||
// Spaces should be removed from non-text data URLs (we already tested
|
// Spaces should NOT be removed from non-base64 encoded data URLs.
|
||||||
// spaces above).
|
|
||||||
{"data:image/fractal,a b c d e f g", true, "image/fractal", "",
|
{"data:image/fractal,a b c d e f g", true, "image/fractal", "",
|
||||||
"abcdefg"},
|
KeepWhitespace() ? "a b c d e f g" : "abcdefg"},
|
||||||
|
|
||||||
// Spaces should also be removed from anything base-64 encoded
|
// Spaces should also be removed from anything base-64 encoded
|
||||||
{"data:;base64,aGVs bG8gd2 9ybGQ=", true, "text/plain", "US-ASCII",
|
{"data:;base64,aGVs bG8gd2 9ybGQ=", true, "text/plain", "US-ASCII",
|
||||||
@@ -109,9 +122,9 @@ TEST_P(DataURLTest, Parse) {
|
|||||||
"%20",
|
"%20",
|
||||||
true, "text/javascript", "", "d4 = 'four';"},
|
true, "text/javascript", "", "d4 = 'four';"},
|
||||||
|
|
||||||
// Only unescaped whitespace should be stripped in non-base64.
|
// All whitespace should be preserved on non-base64 encoded content.
|
||||||
// http://b/1157796
|
{"data:img/png,A B %20 %0A C", true, "img/png", "",
|
||||||
{"data:img/png,A B %20 %0A C", true, "img/png", "", "AB \nC"},
|
KeepWhitespace() ? "A B \n C" : "AB \nC"},
|
||||||
|
|
||||||
{"data:text/plain;charset=utf-8;base64,SGVsbMO2", true, "text/plain",
|
{"data:text/plain;charset=utf-8;base64,SGVsbMO2", true, "text/plain",
|
||||||
"utf-8", "Hell\xC3\xB6"},
|
"utf-8", "Hell\xC3\xB6"},
|
||||||
@@ -332,4 +345,29 @@ TEST_P(DataURLTest, Image) {
|
|||||||
EXPECT_EQ(value, "image/png");
|
EXPECT_EQ(value, "image/png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests the application of the kRemoveWhitespaceForDataURLs command line
|
||||||
|
// switch.
|
||||||
|
TEST(DataURLRemoveWhitespaceTest, Parse) {
|
||||||
|
base::CommandLine::ForCurrentProcess()->AppendSwitch(
|
||||||
|
kRemoveWhitespaceForDataURLs);
|
||||||
|
const ParseTestData tests[] = {
|
||||||
|
{"data:image/fractal,a b c d e f g", true, "image/fractal", "",
|
||||||
|
"abcdefg"},
|
||||||
|
{"data:img/png,A B %20 %0A C", true, "img/png", "", "AB \nC"},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& test : tests) {
|
||||||
|
SCOPED_TRACE(test.url);
|
||||||
|
|
||||||
|
std::string mime_type;
|
||||||
|
std::string charset;
|
||||||
|
std::string data;
|
||||||
|
bool ok = DataURL::Parse(GURL(test.url), &mime_type, &charset, &data);
|
||||||
|
EXPECT_EQ(ok, test.is_valid);
|
||||||
|
EXPECT_EQ(test.mime_type, mime_type);
|
||||||
|
EXPECT_EQ(test.charset, charset);
|
||||||
|
EXPECT_EQ(test.data, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
|
@@ -596,4 +596,8 @@ BASE_FEATURE(kLegacyPKCS1ForTLS13,
|
|||||||
"LegacyPKCS1ForTLS13",
|
"LegacyPKCS1ForTLS13",
|
||||||
base::FEATURE_ENABLED_BY_DEFAULT);
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||||
|
|
||||||
|
BASE_FEATURE(kKeepWhitespaceForDataUrls,
|
||||||
|
"KeepWhitespaceForDataUrls",
|
||||||
|
base::FEATURE_ENABLED_BY_DEFAULT);
|
||||||
|
|
||||||
} // namespace net::features
|
} // namespace net::features
|
||||||
|
@@ -607,6 +607,9 @@ NET_EXPORT BASE_DECLARE_FEATURE(kOptimizeParsingDataUrls);
|
|||||||
// support RSA-PSS.
|
// support RSA-PSS.
|
||||||
NET_EXPORT BASE_DECLARE_FEATURE(kLegacyPKCS1ForTLS13);
|
NET_EXPORT BASE_DECLARE_FEATURE(kLegacyPKCS1ForTLS13);
|
||||||
|
|
||||||
|
// Keep whitespace for non-base64 encoded data: URLs.
|
||||||
|
NET_EXPORT BASE_DECLARE_FEATURE(kKeepWhitespaceForDataUrls);
|
||||||
|
|
||||||
} // namespace net::features
|
} // namespace net::features
|
||||||
|
|
||||||
#endif // NET_BASE_FEATURES_H_
|
#endif // NET_BASE_FEATURES_H_
|
||||||
|
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.serviceworker-expected.txt
vendored
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.serviceworker-expected.txt
vendored
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.sharedworker-expected.txt
vendored
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.sharedworker-expected.txt
vendored
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.worker-expected.txt
vendored
8
third_party/blink/web_tests/external/wpt/fetch/data-urls/processing.any.worker-expected.txt
vendored
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
This is a testharness.js-based test.
|
|
||||||
[FAIL] XHR method GET with MIME type image/png
|
|
||||||
assert_equals: expected "Hello, World!" but got "Hello,World!"
|
|
||||||
Harness: the test ran to completion.
|
|
||||||
|
|
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
@@ -1,17 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
@@ -1,19 +1,11 @@
|
|||||||
This is a testharness.js-based test.
|
This is a testharness.js-based test.
|
||||||
Found 22 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||||
[FAIL] "data://test:test/,X"
|
|
||||||
assert_unreached: Should have rejected: undefined Reached unreachable code
|
|
||||||
[FAIL] "data:;x=x;charset=x,X"
|
[FAIL] "data:;x=x;charset=x,X"
|
||||||
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
|
||||||
[FAIL] "data:;x=x,X"
|
[FAIL] "data:;x=x,X"
|
||||||
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
|
||||||
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
|
||||||
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
assert_equals: expected "image/gif;hi=x" but got "image/gif"
|
||||||
[FAIL] "data:image/png,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:application/javascript,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:unknown/unknown,X X"
|
|
||||||
assert_array_equals: lengths differ, expected array [88, 32, 88] length 3, got object "88,88" length 2
|
|
||||||
[FAIL] "data:text/plain;a=\\",\\",X"
|
[FAIL] "data:text/plain;a=\\",\\",X"
|
||||||
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
|
||||||
[FAIL] "data:text/plain;a=%2C,X"
|
[FAIL] "data:text/plain;a=%2C,X"
|
||||||
|
@@ -2161,6 +2161,7 @@ chromium-metrics-reviews@google.com.
|
|||||||
<int value="1295" label="HelpMeReadSettings"/>
|
<int value="1295" label="HelpMeReadSettings"/>
|
||||||
<int value="1296" label="GenAiDefaultSettings"/>
|
<int value="1296" label="GenAiDefaultSettings"/>
|
||||||
<int value="1297" label="KioskActiveWiFiCredentialsScopeChangeEnabled"/>
|
<int value="1297" label="KioskActiveWiFiCredentialsScopeChangeEnabled"/>
|
||||||
|
<int value="1298" label="DataURLWhitespacePreservationEnabled"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="EnterprisePoliciesSources">
|
<enum name="EnterprisePoliciesSources">
|
||||||
|
Reference in New Issue
Block a user