0

Add support for clearing persist reduce accept language

Implementation of supporting clear persist reduce accept language for a
given origin. It will help clear the cache once user's accept language
preference list changed.

A follow-up CL will implement how we clear the cache:
* https://crrev.com/c/3900577

Public explainer: https://github.com/Tanych/accept-language
I2P:
https://groups.google.com/a/chromium.org/g/blink-dev/c/V4FS3zMbZ08/m/gY02lQaeAgAJ
Design doc[Google internal]: https://docs.google.com/document/d/1bDaCMJP9w6VJjlM_5nRO1KxyB2fkV3JRtKkfUS0GJ_Y
Implementation doc: https://docs.google.com/document/d/1RkPDf7DNtcOj4KXeW8wNCuYfto-drnGYST_NvZe3GoY

Bug: 1323776
Change-Id: Ia84b08adacf4ae175985a2810912ca450fb53804
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3899460
Reviewed-by: Charlie Reis <creis@chromium.org>
Reviewed-by: Colin Blundell <blundell@chromium.org>
Reviewed-by: Andrew Williams <awillia@chromium.org>
Commit-Queue: Victor Tan <victortan@chromium.org>
Reviewed-by: Nathan Eliason <eliason@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1064867}
This commit is contained in:
Victor Tan
2022-10-28 16:13:53 +00:00
committed by Chromium LUCI CQ
parent 59735d5058
commit 8c3d371062
9 changed files with 99 additions and 39 deletions

@ -124,6 +124,18 @@ void ReduceAcceptLanguageService::PersistReducedLanguage(
language.size());
}
void ReduceAcceptLanguageService::ClearReducedLanguage(
const url::Origin& origin) {
const GURL& url = origin.GetURL();
// Only reduce accept-language in http and https scheme.
if (!url.SchemeIsHTTPOrHTTPS())
return;
settings_map_->SetWebsiteSettingDefaultScope(
url, GURL(), ContentSettingsType::REDUCED_ACCEPT_LANGUAGE, base::Value());
}
void ReduceAcceptLanguageService::UpdateAcceptLanguage() {
// In incognito mode return only the first language.
std::string accept_languages_str = net::HttpUtil::ExpandLanguageList(
@ -134,4 +146,4 @@ void ReduceAcceptLanguageService::UpdateAcceptLanguage() {
accept_languages_str, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
}
} // namespace reduce_accept_language
} // namespace reduce_accept_language

@ -39,6 +39,8 @@ class ReduceAcceptLanguageService
void PersistReducedLanguage(const url::Origin& origin,
const std::string& language) override;
void ClearReducedLanguage(const url::Origin& origin) override;
private:
// Forwards changes to `pref_accept_language_` to `user_accept_languages_`,
// after formatting them as appropriate.

@ -29,59 +29,86 @@ ReduceAcceptLanguageServiceTester::ReduceAcceptLanguageServiceTester(
: settings_map_(settings_map), service_(service), prefs_(prefs) {}
void ReduceAcceptLanguageServiceTester::VerifyFetchAcceptLanguageList(
const std::vector<std::string>& expected_langauges) const {
const std::vector<std::string>& languages =
const std::vector<std::string>& expected_languages) const {
const std::vector<std::string>& persisted_languages =
service_->GetUserAcceptLanguages();
EXPECT_EQ(languages, expected_langauges);
EXPECT_EQ(persisted_languages, expected_languages);
}
void ReduceAcceptLanguageServiceTester::VerifyPersistFail(
const GURL& host,
const std::string& lang) const {
service_->PersistReducedLanguage(url::Origin::Create(host), lang);
const std::string& language) const {
service_->PersistReducedLanguage(url::Origin::Create(host), language);
const absl::optional<std::string>& language =
const absl::optional<std::string>& persisted_language =
service_->GetReducedLanguage(url::Origin::Create(host));
EXPECT_FALSE(language.has_value());
EXPECT_FALSE(persisted_language.has_value());
}
void ReduceAcceptLanguageServiceTester::VerifyPersistSuccessOnJavaScriptDisable(
const GURL& host,
const std::string& lang) const {
const std::string& language) const {
settings_map_->SetContentSettingDefaultScope(
host, GURL(), ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
VerifyPersistSuccess(host, lang);
VerifyPersistSuccess(host, language);
// Clear settings map changes to avoid side effects for other tests.
settings_map_->SetWebsiteSettingDefaultScope(
host, GURL(), ContentSettingsType::JAVASCRIPT, base::Value());
}
void ReduceAcceptLanguageServiceTester::VerifyPersistSuccess(
const GURL& host,
const std::string& lang) const {
const std::string& language) const {
base::HistogramTester histograms;
service_->PersistReducedLanguage(url::Origin::Create(host), lang);
const absl::optional<std::string>& language =
service_->GetReducedLanguage(url::Origin::Create(host));
EXPECT_TRUE(language.has_value());
EXPECT_EQ(language.value(), lang);
url::Origin origin = url::Origin::Create(host);
service_->PersistReducedLanguage(origin, language);
const absl::optional<std::string>& persisted_language =
service_->GetReducedLanguage(origin);
EXPECT_TRUE(persisted_language.has_value());
EXPECT_EQ(persisted_language.value(), language);
histograms.ExpectTotalCount("ReduceAcceptLanguage.StoreLatency", 1);
histograms.ExpectUniqueSample("ReduceAcceptLanguage.UpdateSize", lang.size(),
1);
histograms.ExpectUniqueSample("ReduceAcceptLanguage.UpdateSize",
language.size(), 1);
service_->ClearReducedLanguage(origin);
EXPECT_FALSE(service_->GetReducedLanguage(origin).has_value());
}
void ReduceAcceptLanguageServiceTester::VerifyPersistMultipleHostsSuccess(
const std::vector<GURL>& hosts,
const std::vector<std::string>& langs) const {
EXPECT_EQ(hosts.size(), langs.size());
const std::vector<std::string>& languages) const {
EXPECT_EQ(hosts.size(), languages.size());
for (size_t i = 0; i < hosts.size(); i++) {
service_->PersistReducedLanguage(url::Origin::Create(hosts[i]), langs[i]);
service_->PersistReducedLanguage(url::Origin::Create(hosts[i]),
languages[i]);
const absl::optional<std::string>& language =
const absl::optional<std::string>& persisted_language =
service_->GetReducedLanguage(url::Origin::Create(hosts[i]));
EXPECT_TRUE(language.has_value());
EXPECT_EQ(language.value(), langs[i]);
EXPECT_TRUE(persisted_language.has_value());
EXPECT_EQ(persisted_language.value(), languages[i]);
}
// Clear first origin storage and verify the first origin has no persisted
// language.
url::Origin clear_origin = url::Origin::Create(hosts[0]);
service_->ClearReducedLanguage(clear_origin);
EXPECT_FALSE(service_->GetReducedLanguage(clear_origin).has_value());
// Verify other origins still have the persisted language.
for (size_t i = 1; i < hosts.size(); i++) {
const absl::optional<std::string>& persisted_language =
service_->GetReducedLanguage(url::Origin::Create(hosts[i]));
EXPECT_TRUE(persisted_language.has_value());
EXPECT_EQ(persisted_language.value(), languages[i]);
// Clear persisted language to avoid side effects for other tests.
service_->ClearReducedLanguage(url::Origin::Create(hosts[i]));
}
}
} // namespace reduce_accept_language::test
} // namespace reduce_accept_language::test

@ -29,25 +29,27 @@ class ReduceAcceptLanguageServiceTester {
// Checks whether read accept language lists from language prefs as expected.
void VerifyFetchAcceptLanguageList(
const std::vector<std::string>& expected_langauges) const;
const std::vector<std::string>& expected_languages) const;
// Checks whether JavaScriptAllowed works as expected.
void VerifyIsJavaScriptAllowed(const GURL& host) const;
// Checks whether persisted |lang| failed when provided host.
void VerifyPersistFail(const GURL& host, const std::string& lang) const;
// Checks whether persisted `language` failed when provided host.
void VerifyPersistFail(const GURL& host, const std::string& language) const;
// Checks whether persisted |lang| success when JavaScript is disabled.
void VerifyPersistSuccessOnJavaScriptDisable(const GURL& host,
const std::string& lang) const;
// Checks whether persisted `language` success when JavaScript is disabled.
void VerifyPersistSuccessOnJavaScriptDisable(
const GURL& host,
const std::string& language) const;
// Checks whether persisted |lang| success.
void VerifyPersistSuccess(const GURL& host, const std::string& lang) const;
// Checks whether persisted `language` success.
void VerifyPersistSuccess(const GURL& host,
const std::string& language) const;
// Checks whether persisted |lang| success.
// Checks whether persisted `languages` success.
void VerifyPersistMultipleHostsSuccess(
const std::vector<GURL>& hosts,
const std::vector<std::string>& langs) const;
const std::vector<std::string>& languages) const;
private:
raw_ptr<HostContentSettingsMap> settings_map_ = nullptr;

@ -2895,10 +2895,14 @@ class WebContentsImplBrowserTestReduceAcceptLanguageOn
->browser_context()
->GetReduceAcceptLanguageControllerDelegate();
delegate->PersistReducedLanguage(url::Origin::Create(url), persist_lang);
url::Origin origin = url::Origin::Create(url);
delegate->PersistReducedLanguage(origin, persist_lang);
const absl::optional<std::string>& language =
delegate->GetReducedLanguage(url::Origin::Create(url));
delegate->GetReducedLanguage(origin);
EXPECT_EQ(expect_lang, language);
delegate->ClearReducedLanguage(origin);
EXPECT_FALSE(delegate->GetReducedLanguage(origin).has_value());
}
private:

@ -28,6 +28,9 @@ class CONTENT_EXPORT ReduceAcceptLanguageControllerDelegate {
// top-level frames with the same origin.
virtual void PersistReducedLanguage(const url::Origin& origin,
const std::string& language) = 0;
// Clear the persisted reduced language for the given origin.
virtual void ClearReducedLanguage(const url::Origin& origin) = 0;
};
} // namespace content

@ -58,4 +58,12 @@ void MockReduceAcceptLanguageControllerDelegate::PersistReducedLanguage(
reduce_accept_language_map_[origin] = language;
}
} // namespace content
void MockReduceAcceptLanguageControllerDelegate::ClearReducedLanguage(
const url::Origin& origin) {
if (!origin.GetURL().SchemeIsHTTPOrHTTPS()) {
return;
}
reduce_accept_language_map_.erase(origin);
}
} // namespace content

@ -36,6 +36,8 @@ class MockReduceAcceptLanguageControllerDelegate
void PersistReducedLanguage(const url::Origin& origin,
const std::string& language) override;
void ClearReducedLanguage(const url::Origin& origin) override;
private:
std::vector<std::string> user_accept_languages_;
std::map<url::Origin, std::string> reduce_accept_language_map_;

@ -89,4 +89,4 @@ IN_PROC_BROWSER_TEST_F(ReduceAcceptLanguageServiceTest,
{"en-US", "es-MX", "zh-CN"});
}
} // namespace weblayer
} // namespace weblayer