1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
// 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 "chrome/common/extensions/webstore_override.h"
#include <array>
#include <string>
#include <string_view>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/no_destructor.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "extensions/common/context_data.h"
#include "extensions/common/extension.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/mojom/context_type.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace {
// The set of features which this delegated availability check should apply to,
// which correspond to the features used by the webstore.
constexpr static std::array<std::string_view, 2> kWebstoreOverrideFeatureList =
{
// LINT.IfChange
"webstorePrivate", "management",
// LINT.ThenChange(chrome/common/extensions/extension_test_util.cc)
};
// Returns true if the "apps-gallery-url" command line flag has been used to
// specify a webstore override URL and if that URL is the same origin with the
// `url` this function is called with.
//
// Normally the APIs used by the webstore are only exposed to the actual domain
// used by the store, but this delegated availability check allows them to be
// exposed on a specified override URL. This is used both for our own API test
// and externally by the webstore team.
//
// Called by `SimpleFeature::IsAvailableToContextImpl()`, once that function
// determines that the feature has a "delegated availability check" and runs
// the check that was installed by `CreateAvailabilityCheckMap()` when the
// Extensions client was initialized.
bool AreWebstoreFeaturesAvailable(const std::string& api_full_name,
const extensions::Extension* extension,
extensions::mojom::ContextType context,
const GURL& url,
extensions::Feature::Platform platform,
int context_id,
bool check_developer_mode,
const extensions::ContextData& context_data) {
// We use a static local variable here to save on recreating it for repeated
// calls. This is safe since the command line flags are constant for the
// duration of the process.
static base::NoDestructor<GURL> override_url([]() {
std::string override_url_str =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kAppsGalleryURL);
// Empty string means the command line switch was not used.
if (override_url_str.empty()) {
return GURL();
}
return GURL(override_url_str);
}());
if (!override_url->is_valid()) {
// No override URL was specified. Early out.
return false;
}
if (extension) {
return false;
}
if (context != extensions::mojom::ContextType::kWebPage) {
return false;
}
if (!base::Contains(kWebstoreOverrideFeatureList, api_full_name)) {
return false;
}
// We only consider the scheme, domain and port of the supplied override URL,
// which must match the current URL.
if (!url.SchemeIs(override_url->scheme())) {
return false;
}
if (!url.DomainIs(override_url->host())) {
return false;
}
// We only compare port if one was supplied in the override URL, otherwise we
// ignore it completely.
if (override_url->has_port() && url.port() != override_url->port()) {
return false;
}
return true;
}
} // namespace
namespace extensions::webstore_override {
Feature::FeatureDelegatedAvailabilityCheckMap CreateAvailabilityCheckMap() {
Feature::FeatureDelegatedAvailabilityCheckMap map;
for (const auto item : kWebstoreOverrideFeatureList) {
map.emplace(item, base::BindRepeating(&AreWebstoreFeaturesAvailable));
}
return map;
}
} // namespace extensions::webstore_override
|