From: uazo Date: Sat, 15 Apr 2023 11:48:49 +0000 Subject: Internal firewall Introduces a kind of firewall on http calls made by the browser that allows selective blocking via the NetworkTrafficAnnotationTag. allowed or explicitly blocked calls are defined in services/firewall/tools/rules.xml License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html --- chrome/browser/BUILD.gn | 1 + chrome/browser/about_flags.cc | 6 + .../downloads/offline_page_download_bridge.cc | 32 +- .../content/internal/context_menu_download.cc | 32 +- .../android/webapk/webapk_icon_hasher.cc | 32 +- net/BUILD.gn | 1 + .../network_traffic_annotation.h | 4 - net/url_request/url_request_http_job.cc | 15 + net/url_request/url_request_http_job.h | 3 + services/firewall/public/BUILD.gn | 70 +++ services/firewall/public/firewall_features.cc | 28 ++ services/firewall/public/firewall_features.h | 31 ++ services/firewall/public/firewall_service.cc | 46 ++ services/firewall/public/firewall_service.h | 57 +++ services/firewall/tools/annotation_model.py | 49 ++ services/firewall/tools/annotations.xml | 466 ++++++++++++++++++ services/firewall/tools/builders_template.py | 72 +++ services/firewall/tools/codegen.py | 82 +++ services/firewall/tools/decode_template.py | 85 ++++ services/firewall/tools/gen_builders.py | 65 +++ services/firewall/tools/rules.xml | 83 ++++ services/firewall/tools/rules_model.py | 35 ++ services/network/network_context.cc | 73 +++ .../network/public/cpp/simple_url_loader.cc | 18 + .../network/public/cpp/simple_url_loader.h | 3 + .../platform/loader/fetch/fetch_utils.cc | 191 ++++++- .../loader/fetch/url_loader/url_loader.cc | 4 +- .../scripts/auditor/auditor.py | 1 + .../scripts/auditor/util.py | 1 + 29 files changed, 1566 insertions(+), 20 deletions(-) create mode 100644 services/firewall/public/BUILD.gn create mode 100644 services/firewall/public/firewall_features.cc create mode 100644 services/firewall/public/firewall_features.h create mode 100644 services/firewall/public/firewall_service.cc create mode 100644 services/firewall/public/firewall_service.h create mode 100644 services/firewall/tools/annotation_model.py create mode 100644 services/firewall/tools/annotations.xml create mode 100644 services/firewall/tools/builders_template.py create mode 100644 services/firewall/tools/codegen.py create mode 100644 services/firewall/tools/decode_template.py create mode 100644 services/firewall/tools/gen_builders.py create mode 100644 services/firewall/tools/rules.xml create mode 100644 services/firewall/tools/rules_model.py diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -2552,6 +2552,7 @@ static_library("browser") { "//third_party/ungoogled:switches", "//services/device/public/mojom", "//services/device/public/mojom:usb", + "//services/firewall/public:firewall_builders", "//services/image_annotation:service", "//services/media_session/public/mojom", "//services/metrics/public/cpp:ukm_builders", diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc @@ -203,6 +203,7 @@ #include "sandbox/policy/features.h" #include "sandbox/policy/switches.h" #include "services/device/public/cpp/device_features.h" +#include "services/firewall/public/firewall_service.h" #include "services/media_session/public/cpp/features.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" @@ -8592,6 +8593,11 @@ const FeatureEntry kFeatureEntries[] = { FEATURE_VALUE_TYPE(page_info::kPageInfoHideSiteSettings)}, #endif // !BUILDFLAG(IS_ANDROID) + {"enable-firewall", + "Enable internal firewall", + "Enable internal firewall", kOsDesktop | kOsAndroid, + FEATURE_VALUE_TYPE(firewall::features::kEnableFirewall)}, + #if !BUILDFLAG(IS_ANDROID) {"page-info-history-desktop", flag_descriptions::kPageInfoHistoryDesktopName, diff --git a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc --- a/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc +++ b/chrome/browser/offline_pages/android/downloads/offline_page_download_bridge.cc @@ -268,13 +268,43 @@ content::WebContents::Getter GetWebContentsGetter( web_contents->GetPrimaryMainFrame()->GetRoutingID()); } +const net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("offline_pages_download_file", R"( + semantics { + sender: "Bromite" + description: + "Offline pages download file" + trigger: "Manual from user." + data: + "binary format" + destination: LOCAL + internal { + contacts { + email: "uazo@users.noreply.github.com" + } + contacts { + email: "uazo@users.noreply.github.com" + } + } + user_data { + type: NONE + } + last_reviewed: "2023-01-01" + } + policy { + cookies_allowed: NO + setting: + "No setting." + policy_exception_justification: "Not implemented." + })"); + void DownloadAsFile(content::WebContents* web_contents, const GURL& url) { content::DownloadManager* dlm = web_contents->GetBrowserContext()->GetDownloadManager(); std::unique_ptr dl_params( content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( web_contents, url, - TRAFFIC_ANNOTATION_WITHOUT_PROTO("Offline pages download file"))); + traffic_annotation)); content::NavigationEntry* entry = web_contents->GetController().GetLastCommittedEntry(); diff --git a/components/download/content/internal/context_menu_download.cc b/components/download/content/internal/context_menu_download.cc --- a/components/download/content/internal/context_menu_download.cc +++ b/components/download/content/internal/context_menu_download.cc @@ -15,6 +15,36 @@ namespace download { +const net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("download_via_context_menu", R"( + semantics { + sender: "Bromite" + description: + "Download from context menu" + trigger: "Manual from user." + data: + "binary format" + destination: LOCAL + internal { + contacts { + email: "uazo@users.noreply.github.com" + } + contacts { + email: "uazo@users.noreply.github.com" + } + } + user_data { + type: NONE + } + last_reviewed: "2023-01-01" + } + policy { + cookies_allowed: NO + setting: + "No setting." + policy_exception_justification: "Not implemented." + })"); + void CreateContextMenuDownload(content::WebContents* web_contents, const content::ContextMenuParams& params, const std::string& origin, @@ -27,7 +57,7 @@ void CreateContextMenuDownload(content::WebContents* web_contents, std::unique_ptr dl_params( content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( web_contents, url, - TRAFFIC_ANNOTATION_WITHOUT_PROTO("Download via context menu"))); + traffic_annotation)); content::Referrer referrer = content::Referrer::SanitizeForRequest( url, content::Referrer(referring_url.GetAsReferrer(), params.referrer_policy)); diff --git a/components/webapps/browser/android/webapk/webapk_icon_hasher.cc b/components/webapps/browser/android/webapk/webapk_icon_hasher.cc --- a/components/webapps/browser/android/webapk/webapk_icon_hasher.cc +++ b/components/webapps/browser/android/webapk/webapk_icon_hasher.cc @@ -121,6 +121,36 @@ void WebApkIconHasher::DownloadAndComputeMurmur2HashWithTimeout( std::move(callback)); } +const net::NetworkTrafficAnnotationTag traffic_annotation = + net::DefineNetworkTrafficAnnotation("webapk_icon_hasher", R"( + semantics { + sender: "webapk icon hasher" + description: + "webapk icon hasher" + trigger: "Manual or automatic." + data: + " binary format" + destination: WEBSITE + internal { + contacts { + email: "uazo@users.noreply.github.com" + } + contacts { + email: "uazo@users.noreply.github.com" + } + } + user_data { + type: NONE + } + last_reviewed: "2023-01-01" + } + policy { + cookies_allowed: NO + setting: + "No setting." + policy_exception_justification: "Not implemented." + })"); + WebApkIconHasher::WebApkIconHasher( network::mojom::URLLoaderFactory* url_loader_factory, base::WeakPtr web_contents, @@ -145,7 +175,7 @@ WebApkIconHasher::WebApkIconHasher( resource_request->url = webapk_icon.url(); simple_url_loader_ = network::SimpleURLLoader::Create( std::move(resource_request), - TRAFFIC_ANNOTATION_WITHOUT_PROTO("webapk icon hasher")); + traffic_annotation); simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_factory, base::BindOnce(&WebApkIconHasher::OnSimpleLoaderComplete, diff --git a/net/BUILD.gn b/net/BUILD.gn --- a/net/BUILD.gn +++ b/net/BUILD.gn @@ -1096,6 +1096,7 @@ component("net") { "//build:chromeos_buildflags", "//net/data/ssl/chrome_root_store:gen_root_store_inc", "//net/http:transport_security_state_generated_files", + "//services/firewall/public:firewall_builders", "//components/network_session_configurator/common" ] diff --git a/net/traffic_annotation/network_traffic_annotation.h b/net/traffic_annotation/network_traffic_annotation.h --- a/net/traffic_annotation/network_traffic_annotation.h +++ b/net/traffic_annotation/network_traffic_annotation.h @@ -373,10 +373,6 @@ struct MutablePartialNetworkTrafficAnnotationTag { } // namespace net // Placeholder for unannotated usages. -#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) -#define TRAFFIC_ANNOTATION_WITHOUT_PROTO(ANNOTATION_ID) \ - net::DefineNetworkTrafficAnnotation(ANNOTATION_ID, "No proto yet.") -#endif // These annotations are unavailable on desktop Linux + Windows. They are // available on other platforms, since we only audit network annotations on diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc @@ -261,6 +261,9 @@ URLRequestHttpJob::URLRequestHttpJob( throttling_entry_ = manager->RegisterRequestUrl(request->url()); ResetTimer(); + + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) + firewall_service_ = std::make_unique(nullptr); } URLRequestHttpJob::~URLRequestHttpJob() { @@ -555,6 +558,18 @@ void URLRequestHttpJob::MaybeStartTransactionInternal(int result) { void URLRequestHttpJob::StartTransactionInternal() { DCHECK(!override_response_headers_); + if (firewall_service_ && + !firewall_service_->IsAllowed(request_->traffic_annotation().unique_id_hash_code)) { + auto entry = firewall_service_->GetEntry(request_->traffic_annotation().unique_id_hash_code); + LOG(INFO) << "---ABORTED URLRequestHttpJob: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << request_->traffic_annotation().unique_id_hash_code << ")" + << " url: " << request_->original_url().possibly_invalid_spec() + << " path: " << (entry.has_value() ? entry->path : "no-path"); + Kill(); + return; + } + // NOTE: This method assumes that request_info_ is already setup properly. // If we already have a transaction, then we should restart the transaction diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h @@ -31,6 +31,7 @@ #include "net/url_request/url_request_job.h" #include "net/url_request/url_request_throttler_entry_interface.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "services/firewall/public/firewall_service.h" namespace net { @@ -81,6 +82,8 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { return priority_; } + std::unique_ptr firewall_service_; + private: // For CookieRequestScheme histogram enum. FRIEND_TEST_ALL_PREFIXES(URLRequestHttpJobTest, diff --git a/services/firewall/public/BUILD.gn b/services/firewall/public/BUILD.gn new file mode 100644 --- /dev/null +++ b/services/firewall/public/BUILD.gn @@ -0,0 +1,70 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +component("firewall_cpp") { + sources = [ + "firewall_service.h", + "firewall_service.cc", + "firewall_features.h", + "firewall_features.cc", + ] + + defines = [ "FIREWALL_IMPLEMENTATION" ] + + public_deps = [ + "//base", + "//third_party/abseil-cpp:absl" + ] +} + +action("gen_firewall_builders") { + script = "//services/firewall/tools/gen_builders.py" + + inputs = [ + "//services/firewall/tools/gen_builders.py", + "//services/firewall/tools/builders_template.py", + "//services/firewall/tools/rules.xml", + "//services/firewall/tools/annotations.xml", + ] + sources = [ + "//services/firewall/tools/annotations.xml", + "//services/firewall/tools/rules.xml", + ] + + outdir = "$target_gen_dir" + + outputs = [ + outdir + "/firewall_builders.cc", + outdir + "/firewall_builders.h", + outdir + "/annotation_decode.cc", + outdir + "/annotation_decode.h", + ] + + args = [ + "--input", + rebase_path(sources[0], root_build_dir), + "--rules", + rebase_path(sources[1], root_build_dir), + "--output", + rebase_path(outdir, root_build_dir), + ] +} + +static_library("firewall_builders") { + sources = get_target_outputs(":gen_firewall_builders") + + deps = [ + ":gen_firewall_builders", + ":firewall_cpp", + "//base", + ] +} diff --git a/services/firewall/public/firewall_features.cc b/services/firewall/public/firewall_features.cc new file mode 100644 --- /dev/null +++ b/services/firewall/public/firewall_features.cc @@ -0,0 +1,28 @@ +/* + This file is part of Bromite. + + Bromite is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bromite is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bromite. If not, see . +*/ + +#include "firewall_features.h" + +namespace firewall { +namespace features { + +BASE_FEATURE(kEnableFirewall, + "EnableFirewall", + base::FEATURE_ENABLED_BY_DEFAULT); + +} // namespace features +} // namespace firewall diff --git a/services/firewall/public/firewall_features.h b/services/firewall/public/firewall_features.h new file mode 100644 --- /dev/null +++ b/services/firewall/public/firewall_features.h @@ -0,0 +1,31 @@ +/* + This file is part of Bromite. + + Bromite is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bromite is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bromite. If not, see . +*/ + +#ifndef COMPONENTS_FIREWALL_FIREWALL_FEATURES_H_ +#define COMPONENTS_FIREWALL_FIREWALL_FEATURES_H_ + +#include "base/feature_list.h" + +namespace firewall { +namespace features { + +BASE_DECLARE_FEATURE(kEnableFirewall); + +} // namespace features +} // namespace firewall + +#endif // COMPONENTS_FIREWALL_FIREWALL_FEATURES_H_ diff --git a/services/firewall/public/firewall_service.cc b/services/firewall/public/firewall_service.cc new file mode 100644 --- /dev/null +++ b/services/firewall/public/firewall_service.cc @@ -0,0 +1,46 @@ +/* + This file is part of Bromite. + + Bromite is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bromite is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bromite. If not, see . +*/ + +#include "firewall_service.h" + +namespace firewall { + +FirewallService::FirewallService(PrefService* pref_service) + : pref_service_(pref_service) { + decode_map_ = builders::CreateDecodeMap(); +} + +FirewallService::~FirewallService() = default; + +bool FirewallService::IsAllowed(int32_t unique_id_hash_code) { + const auto it = decode_map_.find(unique_id_hash_code); + if (it == decode_map_.end()) + return false; + + return it->second.allowed; +} + +absl::optional FirewallService::GetEntry( + int32_t unique_id_hash_code) const { + const auto it = decode_map_.find(unique_id_hash_code); + if (it == decode_map_.end()) + return absl::nullopt; + + return absl::optional(it->second); +} + +} diff --git a/services/firewall/public/firewall_service.h b/services/firewall/public/firewall_service.h new file mode 100644 --- /dev/null +++ b/services/firewall/public/firewall_service.h @@ -0,0 +1,57 @@ +/* + This file is part of Bromite. + + Bromite is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Bromite is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Bromite. If not, see . +*/ + +#ifndef COMPONENTS_FIREWALL_FIREWALL_SERVICE_H_ +#define COMPONENTS_FIREWALL_FIREWALL_SERVICE_H_ + +#include +#include + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "services/firewall/public/firewall_builders.h" +#include "services/firewall/public/annotation_decode.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +#include "firewall_features.h" + +class PrefService; + +namespace firewall { + +class FirewallService { + public: + FirewallService(PrefService* pref_service); + + FirewallService(const FirewallService&) = delete; + FirewallService& operator=(const FirewallService&) = delete; + + ~FirewallService(); + + bool IsAllowed(int32_t unique_id_hash_code); + absl::optional GetEntry(int32_t unique_id_hash_code) const; + + private: + raw_ptr pref_service_; + firewall::builders::DecodeMap decode_map_; + + base::WeakPtrFactory self_ptr_factory_{this}; +}; + +} // namespace firewall + +#endif // COMPONENTS_FIREWALL_FIREWALL_SERVICE_H_ diff --git a/services/firewall/tools/annotation_model.py b/services/firewall/tools/annotation_model.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/annotation_model.py @@ -0,0 +1,49 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '../../tools/metrics/common')) +import models + +_ITEM_TYPE = models.ObjectNodeType('item', + attributes=[ + ('id', str, r'^[_A-Za-z0-9.]+$'), + ('hash_code', str, r'^[0-9.]+$'), + ('file_path', str, r'^[_/A-Za-z0-9.]*$'), + ('allowed', str, r'^[_/A-Za-z0-9.]*$'), + ], + extra_newlines=(1, 1, 1)) + + +_ANNOTATION_CONFIGURATION_TYPE = models.ObjectNodeType( + 'annotations', + extra_newlines=(2, 1, 1), + indent=False, + children=[ + models.ChildType(_ITEM_TYPE.tag, _ITEM_TYPE, multiple=True), + ]) + +ANNOTATION_XML_TYPE = models.DocumentType(_ANNOTATION_CONFIGURATION_TYPE) + +def PrettifyXML(original_xml): + """Parses the original xml and return a pretty printed version. + + Args: + original_xml: A string containing the original xml file contents. + + Returns: + A pretty-printed xml string, or None if the config contains errors. + """ + config = ANNOTATION_XML_TYPE.Parse(original_xml) + return ANNOTATION_XML_TYPE.PrettyPrint(config) diff --git a/services/firewall/tools/annotations.xml b/services/firewall/tools/annotations.xml new file mode 100644 --- /dev/null +++ b/services/firewall/tools/annotations.xml @@ -0,0 +1,466 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/firewall/tools/builders_template.py b/services/firewall/tools/builders_template.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/builders_template.py @@ -0,0 +1,72 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +"""Templates for generating builder classes for UKM entries.""" + +import codegen + +HEADER = codegen.Template(basename="firewall_builders.h", + file_template=""" +// Generated from //services/firewall/tools/gen_builders.py. DO NOT EDIT! +// source: annotations.xml + +#ifndef {file.guard_path} +#define {file.guard_path} + +#include + +//#include "services/metrics/public/cpp/ukm_entry_builder_base.h" +#include "net/traffic_annotation/network_traffic_annotation.h" + +namespace firewall {{ +namespace builders {{ + +{event_code} + +}} // namespace builders +}} // namespace firewall + +#endif // {file.guard_path} +""", + event_template=""" + extern const char k{event.name}EntryName[]; + extern const uint64_t k{event.name}EntryNameHash; +""", + metric_template=""" +""") + +IMPL = codegen.Template(basename="firewall_builders.cc", + file_template=""" +// Generated from //services/firewall/tools/gen_builders.py. DO NOT EDIT! +// source: annotations.xml + +#include "{file.dir_path}firewall_builders.h" + +namespace firewall {{ +namespace builders {{ + +{event_code} + +}} // namespace builders +}} // namespace firewall +""", + event_template=""" +const char k{event.name}EntryName[] = "{event.raw_name}"; +constexpr uint64_t k{event.name}EntryNameHash = COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("{event.raw_name}"); +""", + metric_template=""" +""") + + +def WriteFiles(outdir, relpath, data): + HEADER.WriteFile(outdir, relpath, data) + IMPL.WriteFile(outdir, relpath, data) diff --git a/services/firewall/tools/codegen.py b/services/firewall/tools/codegen.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/codegen.py @@ -0,0 +1,82 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +import hashlib +import os +import re +import struct +from annotation_model import _ITEM_TYPE + +def to_pascal_case(text): + s = text.replace("-", " ").replace("_", " ") + s = s.split() + if len(text) == 0: + return text + return ''.join(i.capitalize() for i in s[0:]) + +def sanitize_name(name): + s = re.sub('[^0-9a-zA-Z_]', '_', name) + return s + +class FileInfo(object): + def __init__(self, relpath, basename): + self.dir_path = relpath + self.guard_path = sanitize_name(os.path.join(relpath, basename)).upper() + + +class ItemInfo(object): + def __init__(self, json_obj): + self.raw_name = json_obj['id'] + self.name = to_pascal_case(json_obj['id']) + self.hash = json_obj['hash_code'] + self.file_path = json_obj['file_path'] + self.allowed = "false" + if "allowed" in json_obj and json_obj['allowed'] == "1": + self.allowed = "true" + +class Template(object): + """Template for producing code from annotations.xml.""" + + def __init__(self, basename, file_template, event_template, metric_template): + self.basename = basename + self.file_template = file_template + self.event_template = event_template + self.metric_template = metric_template + + def _StampEventCode(self, file_info, item): + event_info = ItemInfo(item) + metric_code = "" + return self.event_template.format( + file=file_info, + event=event_info, + metric_code=metric_code) + + def _StampFileCode(self, relpath, data): + file_info = FileInfo(relpath, self.basename) + event_code = "".join( + self._StampEventCode(file_info, item) + for item in data[_ITEM_TYPE.tag]) + return self.file_template.format( + file=file_info, + event_code=event_code) + + def WriteFile(self, outdir, relpath, data): + """Generates code and writes it to a file. + + Args: + relpath: The path to the file in the source tree. + rootdir: The root of the path the file should be written to. + data: The parsed data. + """ + output = open(os.path.join(outdir, self.basename), 'w') + output.write(self._StampFileCode(relpath, data)) + output.close() diff --git a/services/firewall/tools/decode_template.py b/services/firewall/tools/decode_template.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/decode_template.py @@ -0,0 +1,85 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +"""A template for generating hash decoding code.""" + +import codegen + +HEADER = codegen.Template( +basename="annotation_decode.h", +file_template=""" +// Generated from //services/firewall/tools/gen_builders.py. DO NOT EDIT! +// source: annotations.xml + +#ifndef {file.guard_path} +#define {file.guard_path} + +#include +#include + +namespace firewall {{ +namespace builders {{ + +struct EntryDecoder {{ + const char* name; + bool allowed; + const char* path; +}}; +typedef std::map DecodeMap; +DecodeMap CreateDecodeMap(); + +}} // namespace builders +}} // namespace ukm + +#endif // {file.guard_path} +""", +event_template="", +metric_template="") + +IMPL = codegen.Template( +basename="annotation_decode.cc", +file_template=""" +// Generated from //services/firewall/tools/gen_builders.py. DO NOT EDIT! +// source: annotations.xml + +#include "{file.dir_path}annotation_decode.h" +#include "{file.dir_path}firewall_builders.h" + +namespace firewall {{ +namespace builders {{ + +std::map CreateDecodeMap() {{ + return {{ + {event_code} + }}; +}} + +}} // namespace builders +}} // namespace firewall +""", +event_template=""" + {{ + k{event.name}EntryNameHash, + {{ + k{event.name}EntryName, + {event.allowed}, + "{event.file_path}", + }} + }}, +""", +metric_template=""" +""") + + +def WriteFiles(outdir, relpath, data): + HEADER.WriteFile(outdir, relpath, data) + IMPL.WriteFile(outdir, relpath, data) diff --git a/services/firewall/tools/gen_builders.py b/services/firewall/tools/gen_builders.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/gen_builders.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +"""A utility for generating builder classes for firewall entries. + +It takes as input a rules.xml file describing all of the network annotation entries, +and produces a c++ header and implementation file exposing builders for those +entries. +""" + +import argparse +import sys + +import rules_model +import annotation_model +import builders_template +import decode_template + +parser = argparse.ArgumentParser(description='Generate network annotation entries') +parser.add_argument('--input', help='Path to annotations.xml') +parser.add_argument('--rules', help='Path to rules.xml') +parser.add_argument('--output', help='Path to generated files.') + + +def main(argv): + args = parser.parse_args() + data = ReadFilteredData(args.input) + rules = ReadRulesData(args.rules) + + for key in rules[rules_model._ITEM_TYPE.tag]: + key_id = key["id"] + + for f in data[annotation_model._ITEM_TYPE.tag]: + if f["id"] == key_id: + f["allowed"] = key["allowed"] + #print(f) + + relpath = 'services/firewall/public/' + builders_template.WriteFiles(args.output, relpath, data) + decode_template.WriteFiles(args.output, relpath, data) + return 0 + +def ReadRulesData(path): + with open(path) as rules_file: + data = rules_model.RULES_XML_TYPE.Parse(rules_file.read()) + return data + +def ReadFilteredData(path): + with open(path) as ukm_file: + data = annotation_model.ANNOTATION_XML_TYPE.Parse(ukm_file.read()) + return data + + +if '__main__' == __name__: + sys.exit(main(sys.argv)) diff --git a/services/firewall/tools/rules.xml b/services/firewall/tools/rules.xml new file mode 100644 --- /dev/null +++ b/services/firewall/tools/rules.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/firewall/tools/rules_model.py b/services/firewall/tools/rules_model.py new file mode 100644 --- /dev/null +++ b/services/firewall/tools/rules_model.py @@ -0,0 +1,35 @@ +# This file is part of Bromite. +# Bromite is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Bromite is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with Bromite. If not, see . + +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '../../tools/metrics/common')) +import models + +_ITEM_TYPE = models.ObjectNodeType('item', + attributes=[ + ('id', str, r'^[_A-Za-z0-9.]+$'), + ('allowed', str, r'^[0-9.]+$'), + ], + extra_newlines=(1, 1, 1)) + + +_RULES_CONFIGURATION_TYPE = models.ObjectNodeType( + 'rules', + extra_newlines=(2, 1, 1), + indent=False, + children=[ + models.ChildType(_ITEM_TYPE.tag, _ITEM_TYPE, multiple=True), + ]) + +RULES_XML_TYPE = models.DocumentType(_RULES_CONFIGURATION_TYPE) diff --git a/services/network/network_context.cc b/services/network/network_context.cc --- a/services/network/network_context.cc +++ b/services/network/network_context.cc @@ -88,6 +88,7 @@ #include "net/url_request/url_request.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_builder.h" +#include "services/firewall/public/firewall_service.h" #include "services/network/brokered_client_socket_factory.h" #include "services/network/cookie_manager.h" #include "services/network/cors/cors_url_loader_factory.h" @@ -1622,6 +1623,9 @@ void NetworkContext::OnNewSCTAuditingReportSent() { void NetworkContext::CreateUDPSocket( mojo::PendingReceiver receiver, mojo::PendingRemote listener) { + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + LOG(INFO) << "---LOGGING CreateUDPSocket"; + } socket_factory_->CreateUDPSocket(std::move(receiver), std::move(listener)); } @@ -1634,6 +1638,17 @@ void NetworkContext::CreateRestrictedUDPSocket( mojo::PendingRemote listener, CreateRestrictedUDPSocketCallback callback) { // SimpleHostResolver is transitively owned by |this|. + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + auto firewall_service = std::make_unique(nullptr); + //if (firewall_service->IsAllowed(traffic_annotation.unique_id_hash_code)) { + auto entry = firewall_service->GetEntry(traffic_annotation.unique_id_hash_code); + LOG(INFO) << "---LOGGING CreateRestrictedUDPSocket: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << traffic_annotation.unique_id_hash_code << ")" + << " addr: " << addr.ToString() + << " path: " << (entry.has_value() ? entry->path : "no-path"); + //} + } socket_factory_->CreateRestrictedUDPSocket( addr, mode, traffic_annotation, std::move(params), std::move(receiver), std::move(listener), SimpleHostResolver::Create(this), @@ -1646,6 +1661,17 @@ void NetworkContext::CreateTCPServerSocket( const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojo::PendingReceiver receiver, CreateTCPServerSocketCallback callback) { + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + auto firewall_service = std::make_unique(nullptr); + //if (firewall_service->IsAllowed(traffic_annotation.unique_id_hash_code)) { + auto entry = firewall_service->GetEntry(traffic_annotation.unique_id_hash_code); + LOG(INFO) << "---LOGGING CreateTCPServerSocket: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << traffic_annotation.unique_id_hash_code << ")" + << " local_addr: " << local_addr.ToString() + << " path: " << (entry.has_value() ? entry->path : "no-path"); + //} + } socket_factory_->CreateTCPServerSocket( local_addr, std::move(options), static_cast(traffic_annotation), @@ -1660,6 +1686,21 @@ void NetworkContext::CreateTCPConnectedSocket( mojo::PendingReceiver receiver, mojo::PendingRemote observer, CreateTCPConnectedSocketCallback callback) { + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + auto firewall_service = std::make_unique(nullptr); + //if (firewall_service->IsAllowed(traffic_annotation.unique_id_hash_code)) { + auto entry = firewall_service->GetEntry(traffic_annotation.unique_id_hash_code); + LOG(INFO) << "---LOGGING CreateTCPConnectedSocket: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << traffic_annotation.unique_id_hash_code << ")" + << " addr: " << remote_addr_list.front().ToString() + << " path: " << (entry.has_value() ? entry->path : "no-path"); + // std::move(callback) + // .Run(net::ERR_FAILED, absl::nullopt, absl::nullopt, + // mojo::ScopedDataPipeConsumerHandle(), + // mojo::ScopedDataPipeProducerHandle()); + //} + } socket_factory_->CreateTCPConnectedSocket( local_addr, remote_addr_list, std::move(tcp_connected_socket_options), static_cast(traffic_annotation), @@ -1671,6 +1712,20 @@ void NetworkContext::CreateTCPBoundSocket( const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, mojo::PendingReceiver receiver, CreateTCPBoundSocketCallback callback) { + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + auto firewall_service = std::make_unique(nullptr); + //if (firewall_service->IsAllowed(traffic_annotation.unique_id_hash_code)) { + auto entry = firewall_service->GetEntry(traffic_annotation.unique_id_hash_code); + LOG(INFO) << "---LOGGING CreateTCPBoundSocket: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << traffic_annotation.unique_id_hash_code << ")" + << " path: " << (entry.has_value() ? entry->path : "no-path"); + // std::move(callback) + // .Run(net::ERR_FAILED, absl::nullopt, absl::nullopt, + // mojo::ScopedDataPipeConsumerHandle(), + // mojo::ScopedDataPipeProducerHandle()); + //} + } socket_factory_->CreateTCPBoundSocket( local_addr, static_cast(traffic_annotation), @@ -1736,6 +1791,24 @@ void NetworkContext::CreateWebSocket( mojo::PendingRemote auth_handler, mojo::PendingRemote header_client, const absl::optional& throttling_profile_id) { + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) { + auto firewall_service = std::make_unique(nullptr); + if (!firewall_service->IsAllowed(traffic_annotation.unique_id_hash_code)) { + auto entry = firewall_service->GetEntry(traffic_annotation.unique_id_hash_code); + LOG(INFO) << "---ABORTED CreateWebSocket: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << traffic_annotation.unique_id_hash_code << ")" + << " url " << url + << " path: " << (entry.has_value() ? entry->path : "no-path"); + + mojo::Remote handshake_client_remote( + std::move(handshake_client)); + handshake_client_remote->OnFailure("Insufficient resources", + net::ERR_INSUFFICIENT_RESOURCES, -1); + handshake_client_remote.reset(); + return; + } + } #if BUILDFLAG(ENABLE_WEBSOCKETS) if (!websocket_factory_) websocket_factory_ = std::make_unique(this); diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc --- a/services/network/public/cpp/simple_url_loader.cc +++ b/services/network/public/cpp/simple_url_loader.cc @@ -1240,6 +1240,8 @@ SimpleURLLoaderImpl::SimpleURLLoaderImpl( timeout_timer_(timeout_tick_clock_) { // Allow creation and use on different threads. DETACH_FROM_SEQUENCE(sequence_checker_); + if (base::FeatureList::IsEnabled(firewall::features::kEnableFirewall)) + firewall_service_ = std::make_unique(nullptr); #if DCHECK_IS_ON() if (resource_request_->request_body) { for (const DataElement& element : @@ -1659,6 +1661,22 @@ void SimpleURLLoaderImpl::StartRequest( resource_request_->request_body->AppendDataPipe( string_upload_data_pipe_getter_->GetRemoteForNewUpload()); } + if (firewall_service_ && + !firewall_service_->IsAllowed(annotation_tag_.unique_id_hash_code)) { + auto entry = firewall_service_->GetEntry(annotation_tag_.unique_id_hash_code); + LOG(INFO) << "---ABORTED SimpleURLLoaderImpl: " + << (entry.has_value() ? entry->name : "no-name") + << "(" << annotation_tag_.unique_id_hash_code << ")" + << " url: " << resource_request_->url.possibly_invalid_spec() + << " path: " << (entry.has_value() ? entry->path : "no-path"); + + timeout_timer_.Start( + FROM_HERE, base::Seconds(1), + base::BindOnce(&SimpleURLLoaderImpl::FinishWithResult, + weak_ptr_factory_.GetWeakPtr(), net::ERR_TIMED_OUT)); + return; + } + url_loader_factory->CreateLoaderAndStart( url_loader_.BindNewPipeAndPassReceiver(), request_id_, url_loader_factory_options_, *resource_request_, diff --git a/services/network/public/cpp/simple_url_loader.h b/services/network/public/cpp/simple_url_loader.h --- a/services/network/public/cpp/simple_url_loader.h +++ b/services/network/public/cpp/simple_url_loader.h @@ -17,6 +17,7 @@ #include "services/network/public/cpp/url_loader_completion_status.h" #include "services/network/public/mojom/url_response_head.mojom-forward.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "services/firewall/public/firewall_service.h" class GURL; @@ -395,6 +396,8 @@ class COMPONENT_EXPORT(NETWORK_CPP) SimpleURLLoader { protected: SimpleURLLoader(); + + std::unique_ptr firewall_service_; }; } // namespace network diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_utils.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_utils.cc --- a/third_party/blink/renderer/platform/loader/fetch/fetch_utils.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_utils.cc @@ -97,29 +97,198 @@ net::NetworkTrafficAnnotationTag FetchUtils::GetTrafficAnnotationTag( case network::mojom::RequestDestination::kIframe: case network::mojom::RequestDestination::kFrame: case network::mojom::RequestDestination::kFencedframe: - case network::mojom::RequestDestination::kWebIdentity: NOTREACHED(); [[fallthrough]]; + // Split destination with new annotations + case network::mojom::RequestDestination::kWebIdentity: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_webidentity", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + + case network::mojom::RequestDestination::kServiceWorker: + case network::mojom::RequestDestination::kSharedWorker: + case network::mojom::RequestDestination::kWorker: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_workers", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + + case network::mojom::RequestDestination::kReport: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_report", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + + case network::mojom::RequestDestination::kAudioWorklet: + case network::mojom::RequestDestination::kPaintWorklet: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_worklet", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + + case network::mojom::RequestDestination::kWebBundle: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_webbundle", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + + case network::mojom::RequestDestination::kManifest: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_manifest", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + case network::mojom::RequestDestination::kEmpty: case network::mojom::RequestDestination::kAudio: - case network::mojom::RequestDestination::kAudioWorklet: case network::mojom::RequestDestination::kFont: case network::mojom::RequestDestination::kImage: - case network::mojom::RequestDestination::kManifest: - case network::mojom::RequestDestination::kPaintWorklet: - case network::mojom::RequestDestination::kReport: case network::mojom::RequestDestination::kScript: - case network::mojom::RequestDestination::kServiceWorker: - case network::mojom::RequestDestination::kSharedWorker: case network::mojom::RequestDestination::kStyle: case network::mojom::RequestDestination::kTrack: case network::mojom::RequestDestination::kVideo: - case network::mojom::RequestDestination::kWebBundle: - case network::mojom::RequestDestination::kWorker: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + case network::mojom::RequestDestination::kXslt: + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_xslt", R"( + semantics { + sender: "Blink Resource Loader" + description: + "Blink-initiated request, which includes all resources for " + "normal page loads, chrome URLs, and downloads." + trigger: + "The user navigates to a URL or downloads a file. Also when a " + "webpage, ServiceWorker, or chrome:// uses any network communication." + data: "Anything the initiator wants to send." + destination: OTHER + } + policy { + cookies_allowed: YES + cookies_store: "user" + setting: "These requests cannot be disabled in settings." + policy_exception_justification: + "Not implemented. Without these requests, Chrome will be unable " + "to load any webpage." + })"); + case network::mojom::RequestDestination::kDictionary: - return net::DefineNetworkTrafficAnnotation("blink_resource_loader", R"( + return net::DefineNetworkTrafficAnnotation("blink_resource_loader_dictionary", R"( semantics { sender: "Blink Resource Loader" description: @@ -143,7 +312,7 @@ net::NetworkTrafficAnnotationTag FetchUtils::GetTrafficAnnotationTag( case network::mojom::RequestDestination::kEmbed: case network::mojom::RequestDestination::kObject: return net::DefineNetworkTrafficAnnotation( - "blink_extension_resource_loader", R"( + "blink_extension_resource_loader_embed", R"( semantics { sender: "Blink Resource Loader" description: diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/url_loader.cc @@ -287,7 +287,7 @@ void URLLoader::Context::Start( download_to_blob_registry.InitWithNewPipeAndPassReceiver()); } net::NetworkTrafficAnnotationTag tag = - FetchUtils::GetTrafficAnnotationTag(*request); + FetchUtils::GetTrafficAnnotationTag(*request); // check for deprecation resource_request_sender_->SendSync( std::move(request), tag, loader_options, sync_load_response, url_loader_factory_, std::move(throttles), timeout_interval, @@ -300,7 +300,7 @@ void URLLoader::Context::Start( TRACE_EVENT_WITH_FLOW0("loading", "URLLoader::Context::Start", this, TRACE_EVENT_FLAG_FLOW_OUT); net::NetworkTrafficAnnotationTag tag = - FetchUtils::GetTrafficAnnotationTag(*request); + FetchUtils::GetTrafficAnnotationTag(*request); // check for deprecation request_id_ = resource_request_sender_->SendAsync( std::move(request), GetMaybeUnfreezableTaskRunner(), tag, loader_options, cors_exempt_header_list_, base::WrapRefCounted(this), url_loader_factory_, diff --git a/tools/traffic_annotation/scripts/auditor/auditor.py b/tools/traffic_annotation/scripts/auditor/auditor.py --- a/tools/traffic_annotation/scripts/auditor/auditor.py +++ b/tools/traffic_annotation/scripts/auditor/auditor.py @@ -830,6 +830,7 @@ class ArchivedAnnotation: # the XML. This is used to serialize/deserialize the XML. FIELDS = [ "id", "added_in_milestone", "type", "second_id", "reserved", + "hash_code", "content_hash_code", "os_list", "semantics_fields", "policy_fields", "file_path" ] diff --git a/tools/traffic_annotation/scripts/auditor/util.py b/tools/traffic_annotation/scripts/auditor/util.py --- a/tools/traffic_annotation/scripts/auditor/util.py +++ b/tools/traffic_annotation/scripts/auditor/util.py @@ -73,6 +73,7 @@ def get_current_platform(build_path: Optional[Path] = None) -> str: # It's probably not Android/ChromeOS in that case. pass + current_platform = "android" return current_platform -- 2.25.1