0

Move safe search utility to safe_search_api component.

The supervised user service, one of the main clients of SafeSearch APIs
is migrating to components/ to allow cross-platform URL filtering support.

Move relevant utilities to components to be able to use post migration.

Bug: b/267471715
Change-Id: I4fc2bfaed72df8b1d214ed55b23084636717ee0c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4329546
Reviewed-by: Marc Treib <treib@chromium.org>
Commit-Queue: Nohemi Fernandez <fernandex@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1116507}
This commit is contained in:
Nohemi Fernandez
2023-03-13 18:50:34 +00:00
committed by Chromium LUCI CQ
parent d813f77556
commit 05d59a2a09
24 changed files with 110 additions and 108 deletions

@ -4,6 +4,8 @@
source_set("safe_search_api") {
sources = [
"safe_search_util.cc",
"safe_search_util.h",
"url_checker.cc",
"url_checker.h",
"url_checker_client.h",
@ -58,6 +60,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"safe_search/safe_search_url_checker_client_unittest.cc",
"safe_search_util_unittest.cc",
"url_checker_unittest.cc",
]
deps = [

@ -0,0 +1,116 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/safe_search_api/safe_search_util.h"
#include <string>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "components/google/core/common/google_util.h"
#include "net/cookies/cookie_util.h"
#include "net/http/http_request_headers.h"
#include "url/gurl.h"
namespace {
// Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
// same key as the the |second_parameter| (e.g. foo=baz). Both parameters
// must be in key=value form.
bool HasSameParameterKey(base::StringPiece first_parameter,
base::StringPiece second_parameter) {
DCHECK(second_parameter.find("=") != std::string::npos);
// Prefix for "foo=bar" is "foo=".
base::StringPiece parameter_prefix =
second_parameter.substr(0, second_parameter.find("=") + 1);
return base::StartsWith(first_parameter, parameter_prefix,
base::CompareCase::INSENSITIVE_ASCII);
}
// Examines the query string containing parameters and adds the necessary ones
// so that SafeSearch is active. |query| is the string to examine and the
// return value is the |query| string modified such that SafeSearch is active.
std::string AddSafeSearchParameters(const std::string& query) {
std::vector<base::StringPiece> new_parameters;
std::string safe_parameter = safe_search_api::kSafeSearchSafeParameter;
std::string ssui_parameter = safe_search_api::kSafeSearchSsuiParameter;
for (const base::StringPiece& param : base::SplitStringPiece(
query, "&", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
if (!HasSameParameterKey(param, safe_parameter) &&
!HasSameParameterKey(param, ssui_parameter)) {
new_parameters.push_back(param);
}
}
new_parameters.push_back(safe_parameter);
new_parameters.push_back(ssui_parameter);
return base::JoinString(new_parameters, "&");
}
} // namespace
namespace safe_search_api {
const char kSafeSearchSafeParameter[] = "safe=active";
const char kSafeSearchSsuiParameter[] = "ssui=on";
const char kYouTubeRestrictHeaderName[] = "YouTube-Restrict";
const char kYouTubeRestrictHeaderValueModerate[] = "Moderate";
const char kYouTubeRestrictHeaderValueStrict[] = "Strict";
const char kGoogleAppsAllowedDomains[] = "X-GoogApps-Allowed-Domains";
// If |request| is a request to Google Web Search the function
// enforces that the SafeSearch query parameters are set to active.
// Sets the query part of |new_url| with the new value of the parameters.
void ForceGoogleSafeSearch(const GURL& url, GURL* new_url) {
if (!google_util::IsGoogleSearchUrl(url) &&
!google_util::IsGoogleHomePageUrl(url)) {
return;
}
std::string query = url.query();
std::string new_query = AddSafeSearchParameters(query);
if (query == new_query) {
return;
}
GURL::Replacements replacements;
replacements.SetQueryStr(new_query);
*new_url = url.ReplaceComponents(replacements);
}
void ForceYouTubeRestrict(const GURL& url,
net::HttpRequestHeaders* headers,
YouTubeRestrictMode mode) {
if (!google_util::IsYoutubeDomainUrl(
url, google_util::ALLOW_SUBDOMAIN,
google_util::DISALLOW_NON_STANDARD_PORTS)) {
return;
}
switch (mode) {
case YOUTUBE_RESTRICT_OFF:
case YOUTUBE_RESTRICT_COUNT:
NOTREACHED();
break;
case YOUTUBE_RESTRICT_MODERATE:
headers->SetHeader(kYouTubeRestrictHeaderName,
kYouTubeRestrictHeaderValueModerate);
break;
case YOUTUBE_RESTRICT_STRICT:
headers->SetHeader(kYouTubeRestrictHeaderName,
kYouTubeRestrictHeaderValueStrict);
break;
}
}
} // namespace safe_search_api

@ -0,0 +1,55 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SAFE_SEARCH_API_SAFE_SEARCH_UTIL_H_
#define COMPONENTS_SAFE_SEARCH_API_SAFE_SEARCH_UTIL_H_
class GURL;
namespace net {
class HttpRequestHeaders;
}
namespace safe_search_api {
// Parameters that get appended to force SafeSearch.
extern const char kSafeSearchSafeParameter[];
extern const char kSafeSearchSsuiParameter[];
// Headers set for restricted YouTube.
extern const char kYouTubeRestrictHeaderName[];
extern const char kYouTubeRestrictHeaderValueModerate[];
extern const char kYouTubeRestrictHeaderValueStrict[];
// Header set when restricting allowed domains for apps.
extern const char kGoogleAppsAllowedDomains[];
// Values for YouTube Restricted Mode.
// VALUES MUST COINCIDE WITH ForceYouTubeRestrict POLICY.
enum YouTubeRestrictMode {
YOUTUBE_RESTRICT_OFF = 0, // Do not restrict YouTube content. YouTube
// might still restrict content based on its
// user settings.
YOUTUBE_RESTRICT_MODERATE = 1, // Enforce at least a moderately strict
// content filter for YouTube.
YOUTUBE_RESTRICT_STRICT = 2, // Enforce a strict content filter for YouTube.
YOUTUBE_RESTRICT_COUNT = 3 // Enum counter
};
// If |url| is a url to Google Web Search, enforces that the SafeSearch
// query parameters are set to active. Sets |new_url| to a copy of the request
// url in which the query part contains the new values of the parameters.
void ForceGoogleSafeSearch(const GURL& url, GURL* new_url);
// Does nothing if |url| is not a url to YouTube. Otherwise, if |mode|
// is not |YOUTUBE_RESTRICT_OFF|, enforces a minimum YouTube Restrict mode
// by setting YouTube Restrict header. Setting |YOUTUBE_RESTRICT_OFF| is not
// supported and will do nothing in production.
void ForceYouTubeRestrict(const GURL& url,
net::HttpRequestHeaders* headers,
YouTubeRestrictMode mode);
} // namespace safe_search_api
#endif // COMPONENTS_SAFE_SEARCH_API_SAFE_SEARCH_UTIL_H_

@ -0,0 +1,158 @@
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/safe_search_api/safe_search_util.h"
#include "base/strings/string_piece.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace {
// Does a request using the |url_string| URL and verifies that the expected
// string is equal to the query part (between ? and #) of the final url of
// that request.
void CheckAddedParameters(const std::string& url_string,
const std::string& expected_query_parameters) {
// Show the URL in the trace so we know where we failed.
SCOPED_TRACE(url_string);
GURL result(url_string);
safe_search_api::ForceGoogleSafeSearch(GURL(url_string), &result);
EXPECT_EQ(expected_query_parameters, result.query());
}
TEST(SafeSearchUtilTest, AddGoogleSafeSearchParams) {
const std::string kSafeParameter = safe_search_api::kSafeSearchSafeParameter;
const std::string kSsuiParameter = safe_search_api::kSafeSearchSsuiParameter;
const std::string kBothParameters = kSafeParameter + "&" + kSsuiParameter;
// Test the home page.
CheckAddedParameters("http://google.com/", kBothParameters);
// Test the search home page.
CheckAddedParameters("http://google.com/webhp", kBothParameters);
// Test different valid search pages with parameters.
CheckAddedParameters("http://google.com/search?q=google",
"q=google&" + kBothParameters);
CheckAddedParameters("http://google.com/?q=google",
"q=google&" + kBothParameters);
CheckAddedParameters("http://google.com/webhp?q=google",
"q=google&" + kBothParameters);
// Test the valid pages with safe set to off.
CheckAddedParameters("http://google.com/search?q=google&safe=off",
"q=google&" + kBothParameters);
CheckAddedParameters("http://google.com/?q=google&safe=off",
"q=google&" + kBothParameters);
CheckAddedParameters("http://google.com/webhp?q=google&safe=off",
"q=google&" + kBothParameters);
CheckAddedParameters("http://google.com/webhp?q=google&%73afe=off",
"q=google&%73afe=off&" + kBothParameters);
// Test the home page, different TLDs.
CheckAddedParameters("http://google.de/", kBothParameters);
CheckAddedParameters("http://google.ro/", kBothParameters);
CheckAddedParameters("http://google.nl/", kBothParameters);
// Test the search home page, different TLD.
CheckAddedParameters("http://google.de/webhp", kBothParameters);
// Test the search page with parameters, different TLD.
CheckAddedParameters("http://google.de/search?q=google",
"q=google&" + kBothParameters);
// Test the home page with parameters, different TLD.
CheckAddedParameters("http://google.de/?q=google",
"q=google&" + kBothParameters);
// Test the search page with the parameters set.
CheckAddedParameters("http://google.de/?q=google&" + kBothParameters,
"q=google&" + kBothParameters);
// Test some possibly tricky combinations.
CheckAddedParameters(
"http://google.com/?q=goog&" + kSafeParameter + "&ssui=one",
"q=goog&" + kBothParameters);
CheckAddedParameters(
"http://google.de/?q=goog&unsafe=active&" + kSsuiParameter,
"q=goog&unsafe=active&" + kBothParameters);
CheckAddedParameters("http://google.de/?q=goog&safe=off&ssui=off",
"q=goog&" + kBothParameters);
CheckAddedParameters("http://google.de/?q=&tbs=rimg:",
"q=&tbs=rimg:&" + kBothParameters);
// Test various combinations where we should not add anything.
CheckAddedParameters(
"http://google.com/?q=goog&" + kSsuiParameter + "&" + kSafeParameter,
"q=goog&" + kBothParameters);
CheckAddedParameters(
"http://google.com/?" + kSsuiParameter + "&q=goog&" + kSafeParameter,
"q=goog&" + kBothParameters);
CheckAddedParameters(
"http://google.com/?" + kSsuiParameter + "&" + kSafeParameter + "&q=goog",
"q=goog&" + kBothParameters);
// Test that another website is not affected, without parameters.
CheckAddedParameters("http://google.com/finance", std::string());
// Test that another website is not affected, with parameters.
CheckAddedParameters("http://google.com/finance?q=goog", "q=goog");
// Test with percent-encoded data (%26 is &)
CheckAddedParameters("http://google.com/?q=%26%26%26&" + kSsuiParameter +
"&" + kSafeParameter + "&param=%26%26%26",
"q=%26%26%26&param=%26%26%26&" + kBothParameters);
// Test with image search
CheckAddedParameters("http://google.com/imgres?imgurl=https://image",
"imgurl=https://image&" + kBothParameters);
}
TEST(SafeSearchUtilTest, SetYoutubeHeader) {
net::HttpRequestHeaders headers;
safe_search_api::ForceYouTubeRestrict(
GURL("http://www.youtube.com"), &headers,
safe_search_api::YOUTUBE_RESTRICT_MODERATE);
std::string value;
EXPECT_TRUE(headers.GetHeader("Youtube-Restrict", &value));
EXPECT_EQ("Moderate", value);
}
TEST(SafeSearchUtilTest, OverrideYoutubeHeader) {
net::HttpRequestHeaders headers;
headers.SetHeader("Youtube-Restrict", "Off");
safe_search_api::ForceYouTubeRestrict(
GURL("http://www.youtube.com"), &headers,
safe_search_api::YOUTUBE_RESTRICT_MODERATE);
std::string value;
EXPECT_TRUE(headers.GetHeader("Youtube-Restrict", &value));
EXPECT_EQ("Moderate", value);
}
TEST(SafeSearchUtilTest, DoesntTouchNonYoutubeURL) {
net::HttpRequestHeaders headers;
headers.SetHeader("Youtube-Restrict", "Off");
safe_search_api::ForceYouTubeRestrict(
GURL("http://www.notyoutube.com"), &headers,
safe_search_api::YOUTUBE_RESTRICT_MODERATE);
std::string value;
EXPECT_TRUE(headers.GetHeader("Youtube-Restrict", &value));
EXPECT_EQ("Off", value);
}
} // namespace