#include "extensions/common/cors_util.h"
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "build/chromeos_buildflags.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/url_pattern_set.h"
namespace extensions {
namespace {
uint16_t GetEffectivePort(const std::string& port_string) {
int port_int = 0;
bool success = base::StringToInt(port_string, &port_int);
DCHECK(success) << port_string;
return port_int;
}
void AddURLPatternSetToList(
const URLPatternSet& pattern_set,
std::vector<network::mojom::CorsOriginPatternPtr>* list,
network::mojom::CorsOriginAccessMatchPriority priority) {
static const char* const kSchemes[] = {
content::kChromeUIScheme,
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
content::kArkWebUIScheme,
extensions::kArkwebExtensionScheme,
#endif
#if BUILDFLAG(IS_CHROMEOS)
content::kExternalFileScheme,
#endif
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
extensions::kArkwebExtensionScheme,
#endif
extensions::kExtensionScheme,
url::kFileScheme,
url::kFtpScheme,
url::kHttpScheme,
url::kHttpsScheme,
};
for (const URLPattern& pattern : pattern_set) {
for (const char* const scheme : kSchemes) {
if (!pattern.MatchesScheme(scheme))
continue;
network::mojom::CorsDomainMatchMode domain_match_mode =
pattern.match_subdomains()
? network::mojom::CorsDomainMatchMode::kAllowSubdomains
: network::mojom::CorsDomainMatchMode::kDisallowSubdomains;
network::mojom::CorsPortMatchMode port_match_mode =
(pattern.port() == "*")
? network::mojom::CorsPortMatchMode::kAllowAnyPort
: network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort;
uint16_t port =
(port_match_mode ==
network::mojom::CorsPortMatchMode::kAllowOnlySpecifiedPort)
? GetEffectivePort(pattern.port())
: 0u;
list->push_back(network::mojom::CorsOriginPattern::New(
scheme, pattern.host(), port, domain_match_mode, port_match_mode,
priority));
}
}
}
}
std::vector<network::mojom::CorsOriginPatternPtr>
CreateCorsOriginAccessAllowList(const Extension& extension) {
std::vector<network::mojom::CorsOriginPatternPtr> allow_list;
URLPatternSet origin_permissions =
extension.permissions_data()->GetEffectiveHostPermissions();
AddURLPatternSetToList(
origin_permissions, &allow_list,
network::mojom::CorsOriginAccessMatchPriority::kDefaultPriority);
URLPatternSet policy_allowed_host_patterns =
URLPatternSet::CreateIntersection(
extension.permissions_data()->policy_allowed_hosts(),
origin_permissions, URLPatternSet::IntersectionBehavior::kDetailed);
AddURLPatternSetToList(
policy_allowed_host_patterns, &allow_list,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
return allow_list;
}
std::vector<network::mojom::CorsOriginPatternPtr>
CreateCorsOriginAccessBlockList(const Extension& extension) {
std::vector<network::mojom::CorsOriginPatternPtr> block_list;
AddURLPatternSetToList(
extension.permissions_data()->policy_blocked_hosts(), &block_list,
network::mojom::CorsOriginAccessMatchPriority::kLowPriority);
AddURLPatternSetToList(
extension.permissions_data()->GetUserBlockedHosts(), &block_list,
network::mojom::CorsOriginAccessMatchPriority::kMediumPriority);
GURL webstore_launch_url = extension_urls::GetWebstoreLaunchURL();
block_list.push_back(network::mojom::CorsOriginPattern::New(
webstore_launch_url.GetScheme(), webstore_launch_url.GetHost(),
0, network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kHighPriority));
GURL new_webstore_launch_url = extension_urls::GetNewWebstoreLaunchURL();
block_list.push_back(network::mojom::CorsOriginPattern::New(
new_webstore_launch_url.GetScheme(), new_webstore_launch_url.GetHost(),
0, network::mojom::CorsDomainMatchMode::kAllowSubdomains,
network::mojom::CorsPortMatchMode::kAllowAnyPort,
network::mojom::CorsOriginAccessMatchPriority::kHighPriority));
return block_list;
}
}