0

[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:
Dave Tapuska
2024-09-09 15:03:59 +00:00
committed by Chromium LUCI CQ
parent 8a5bc8d055
commit 34b6c2b36e
23 changed files with 280 additions and 78 deletions
chrome
components/policy
net/base
third_party/blink/web_tests
external
platform
mac-mac13
virtual
keepalive-in-browser-migration
external
mac-mac14-arm64
virtual
keepalive-in-browser-migration
external
mac-mac14
virtual
keepalive-in-browser-migration
external
tools/metrics/histograms/metadata/enterprise

@ -187,6 +187,7 @@
#include "media/audio/audio_manager.h"
#include "media/base/localized_strings.h"
#include "media/media_buildflags.h"
#include "net/base/data_url.h"
#include "net/base/net_module.h"
#include "net/cookies/cookie_monster.h"
#include "net/http/http_network_layer.h"
@ -1179,6 +1180,14 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
// IsolateOrigins policy is taken care of through SiteIsolationPrefsObserver
// (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)
// 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

@ -370,6 +370,7 @@
#include "media/media_buildflags.h"
#include "media/mojo/buildflags.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/data_url.h"
#include "net/base/features.h"
#include "net/cookies/site_for_cookies.h"
#include "net/ssl/client_cert_store.h"
@ -1596,6 +1597,8 @@ void ChromeContentBrowserClient::RegisterLocalStatePrefs(
registry->RegisterBooleanPref(prefs::kSitePerProcess, false);
registry->RegisterBooleanPref(prefs::kTabFreezingEnabled, true);
registry->RegisterIntegerPref(prefs::kSCTAuditingHashdanceReportCount, 0);
registry->RegisterBooleanPref(prefs::kDataURLWhitespacePreservationEnabled,
true);
#if BUILDFLAG(IS_CHROMEOS)
registry->RegisterBooleanPref(prefs::kNativeClientForceAllowed, false);
#endif // BUILDFLAG(IS_CHROMEOS)
@ -3104,6 +3107,13 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
command_line, GetProfilerProcessType(*command_line),
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)

@ -264,6 +264,7 @@ source_set("policy_specific_browser_tests") {
"test/autoplay_policy_browsertest.cc",
"test/bookmark_bar_enabled_browsertest.cc",
"test/component_updater_policy_browsertest.cc",
"test/data_url_policy_browsertest.cc",
"test/developer_tools_policy_browsertest.cc",
"test/download_directory_browsertest.cc",
"test/ipv6_reachability_override_policy_browsertest.cc",

@ -299,6 +299,9 @@ const PolicyToPreferenceMapEntry kSimplePolicyMap[] = {
{ key::kComponentUpdatesEnabled,
prefs::kComponentUpdatesEnabled,
base::Value::Type::BOOLEAN },
{ key::kDataURLWhitespacePreservationEnabled,
prefs::kDataURLWhitespacePreservationEnabled,
base::Value::Type::BOOLEAN },
{ key::kDefaultPopupsSetting,
prefs::kManagedDefaultPopupsSetting,
base::Value::Type::INTEGER },

@ -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.
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.
inline constexpr char kNetworkQualities[] = "net.network_qualities";

@ -1296,6 +1296,7 @@ policies:
1295: HelpMeReadSettings
1296: GenAiDefaultSettings
1297: KioskActiveWiFiCredentialsScopeChangeEnabled
1298: DataURLWhitespacePreservationEnabled
atomic_groups:
1: Homepage

@ -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 "base/base64.h"
#include "base/command_line.h"
#include "base/ranges/algorithm.h"
#include "base/strings/escape.h"
#include "base/strings/string_split.h"
@ -21,8 +22,21 @@
#include "url/gurl.h"
namespace net {
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/#forgiving-base64, does not include \v in the
// set of ASCII whitespace characters the way Unicode does.
@ -157,13 +171,20 @@ bool DataURL::Parse(const GURL& url,
}
}
} 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;
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;
// Strip whitespace for non-text MIME types. This is controlled either by
// the feature (finch kill switch) or an enterprise policy which sets the
// command line flag.
if (!base::FeatureList::IsEnabled(features::kKeepWhitespaceForDataUrls) ||
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);

@ -18,6 +18,12 @@ namespace net {
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.
//
// Briefly, a 'data' URL has the form:

@ -27,22 +27,36 @@ struct ParseTestData {
} // namespace
class DataURLTest : public testing::Test,
public ::testing::WithParamInterface<bool> {
protected:
void SetUp() override {
if (GetParam()) {
feature_list_.InitAndEnableFeature(features::kOptimizeParsingDataUrls);
} else {
feature_list_.InitAndDisableFeature(features::kOptimizeParsingDataUrls);
}
class DataURLTest
: public testing::Test,
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
public:
DataURLTest() {
using FeatureList = std::vector<base::test::FeatureRef>;
FeatureList enabled_features;
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:
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) {
const ParseTestData tests[] = {
@ -89,10 +103,9 @@ TEST_P(DataURLTest, Parse) {
// invalid base64 content
{"data:;base64,aGVs_-_-", false, "", "", ""},
// Spaces should be removed from non-text data URLs (we already tested
// spaces above).
// Spaces should NOT be removed from non-base64 encoded data URLs.
{"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
{"data:;base64,aGVs bG8gd2 9ybGQ=", true, "text/plain", "US-ASCII",
@ -109,9 +122,9 @@ TEST_P(DataURLTest, Parse) {
"%20",
true, "text/javascript", "", "d4 = 'four';"},
// Only unescaped whitespace should be stripped in non-base64.
// http://b/1157796
{"data:img/png,A B %20 %0A C", true, "img/png", "", "AB \nC"},
// All whitespace should be preserved on non-base64 encoded content.
{"data:img/png,A B %20 %0A C", true, "img/png", "",
KeepWhitespace() ? "A B \n C" : "AB \nC"},
{"data:text/plain;charset=utf-8;base64,SGVsbMO2", true, "text/plain",
"utf-8", "Hell\xC3\xB6"},
@ -332,4 +345,29 @@ TEST_P(DataURLTest, Image) {
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

@ -596,4 +596,8 @@ BASE_FEATURE(kLegacyPKCS1ForTLS13,
"LegacyPKCS1ForTLS13",
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kKeepWhitespaceForDataUrls,
"KeepWhitespaceForDataUrls",
base::FEATURE_ENABLED_BY_DEFAULT);
} // namespace net::features

@ -607,6 +607,9 @@ NET_EXPORT BASE_DECLARE_FEATURE(kOptimizeParsingDataUrls);
// support RSA-PSS.
NET_EXPORT BASE_DECLARE_FEATURE(kLegacyPKCS1ForTLS13);
// Keep whitespace for non-base64 encoded data: URLs.
NET_EXPORT BASE_DECLARE_FEATURE(kKeepWhitespaceForDataUrls);
} // namespace net::features
#endif // NET_BASE_FEATURES_H_

@ -1,17 +1,11 @@
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"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -1,17 +1,11 @@
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"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -1,17 +1,11 @@
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"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -1,17 +1,11 @@
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"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[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.
Found 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
[FAIL] "data:;x=x;charset=x,X"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -1,17 +1,11 @@
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"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -1,19 +1,11 @@
This is a testharness.js-based test.
Found 22 FAIL, 0 TIMEOUT, 0 NOTRUN.
[FAIL] "data://test:test/,X"
assert_unreached: Should have rejected: undefined Reached unreachable code
Found 18 FAIL, 0 TIMEOUT, 0 NOTRUN.
[FAIL] "data:;x=x;charset=x,X"
assert_equals: expected "text/plain;x=x;charset=x" but got "text/plain;charset=x"
[FAIL] "data:;x=x,X"
assert_equals: expected "text/plain;x=x" but got "text/plain;charset=US-ASCII"
[FAIL] "data:IMAGE/gif;hi=x,%C2%B1"
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"
assert_equals: expected "text/plain;a=\\"\\"" but got "text/plain"
[FAIL] "data:text/plain;a=%2C,X"

@ -2161,6 +2161,7 @@ chromium-metrics-reviews@google.com.
<int value="1295" label="HelpMeReadSettings"/>
<int value="1296" label="GenAiDefaultSettings"/>
<int value="1297" label="KioskActiveWiFiCredentialsScopeChangeEnabled"/>
<int value="1298" label="DataURLWhitespacePreservationEnabled"/>
</enum>
<enum name="EnterprisePoliciesSources">