blob: 38dd2219798888b56092566368203d646e48614e [file] [log] [blame]
// Copyright 2025 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/browser/web_applications/web_app_scope.h"
#include "base/test/test_future.h"
#include "chrome/browser/web_applications/test/fake_web_app_origin_association_manager.h"
#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
#include "chrome/browser/web_applications/test/fake_web_contents_manager.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_test.h"
#include "chrome/browser/web_applications/web_app_origin_association_manager.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/webapps/common/web_app_id.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace web_app {
namespace {
class WebAppScopeTest : public WebAppTest {
public:
WebAppScopeTest() = default;
~WebAppScopeTest() override = default;
void SetUp() override {
WebAppTest::SetUp();
auto fake_association_manager =
std::make_unique<FakeWebAppOriginAssociationManager>();
fake_association_manager->set_pass_through(true);
fake_provider().SetOriginAssociationManager(
std::move(fake_association_manager));
test::AwaitStartWebAppProviderAndSubsystems(profile());
}
protected:
webapps::AppId InstallWebAppWithScope(const GURL& scope) {
std::unique_ptr<WebAppInstallInfo> web_app_info =
WebAppInstallInfo::CreateForTesting(scope);
return test::InstallWebApp(profile(), std::move(web_app_info));
}
webapps::AppId InstallWebAppWithScopeExtensions(
const GURL& scope,
const std::vector<ScopeExtensionInfo>& scope_extensions) {
std::unique_ptr<WebAppInstallInfo> web_app_info =
WebAppInstallInfo::CreateForTesting(scope);
web_app_info->scope_extensions = base::flat_set<ScopeExtensionInfo>(
scope_extensions.begin(), scope_extensions.end());
return test::InstallWebApp(profile(), std::move(web_app_info));
}
WebAppRegistrar& registrar() { return fake_provider().registrar_unsafe(); }
};
TEST_F(WebAppScopeTest, IsInScopeBasic) {
const GURL scope("https://example.com/");
webapps::AppId app_id = InstallWebAppWithScope(scope);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.com/")));
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.com/path")));
EXPECT_FALSE(web_app_scope->IsInScope(GURL("https://example.org/")));
}
TEST_F(WebAppScopeTest, IsInScopeWithSubdir) {
const GURL scope("https://example.com/subdir/");
webapps::AppId app_id = InstallWebAppWithScope(scope);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.com/subdir/")));
EXPECT_TRUE(
web_app_scope->IsInScope(GURL("https://example.com/subdir/path")));
EXPECT_FALSE(web_app_scope->IsInScope(GURL("https://example.com/")));
EXPECT_FALSE(web_app_scope->IsInScope(GURL("https://example.com/path")));
}
TEST_F(WebAppScopeTest, TestScopeFragmentIgnored) {
const GURL kStartUrl("https://www.foo.com/bar/index.html");
const GURL kScopeWithQueryAndFragments =
GURL("https://www.foo.com/bar/?query=abc#fragment");
std::unique_ptr<WebAppInstallInfo> install_info =
WebAppInstallInfo::CreateWithStartUrlForTesting(kStartUrl);
install_info->scope = kScopeWithQueryAndFragments;
webapps::AppId app_id =
test::InstallWebApp(profile(), std::move(install_info));
EXPECT_TRUE(fake_provider().registrar_unsafe().IsUrlInAppScope(
GURL("https://www.foo.com/bar/"), app_id));
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://www.foo.com/bar/")));
}
TEST_F(WebAppScopeTest, IsInScopeHttpToHttpsUpgrade) {
const GURL scope("http://example.com/");
webapps::AppId app_id = InstallWebAppWithScope(scope);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_TRUE(web_app_scope->IsInScope(GURL("http://example.com/")));
EXPECT_FALSE(web_app_scope->IsInScope(
GURL("https://example.com/"),
WebAppScopeOptions{.allow_http_to_https_upgrade = false}));
EXPECT_TRUE(web_app_scope->IsInScope(
GURL("https://example.com/"),
WebAppScopeOptions{.allow_http_to_https_upgrade = true}));
}
TEST_F(WebAppScopeTest, IsInScopeWithScopeExtensions) {
const GURL scope("https://example.com/");
const std::vector<ScopeExtensionInfo> scope_extensions = {
ScopeExtensionInfo::CreateForOrigin(
url::Origin::Create(GURL("https://example.org"))),
ScopeExtensionInfo::CreateForOrigin(
url::Origin::Create(GURL("https://example.net")),
/*has_origin_wildcard=*/true)};
webapps::AppId app_id =
InstallWebAppWithScopeExtensions(scope, scope_extensions);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.com/")));
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.org/")));
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://sub.example.net/")));
EXPECT_TRUE(web_app_scope->IsInScope(GURL("https://example.net/")));
EXPECT_FALSE(web_app_scope->IsInScope(GURL("https://sub.example.org/")));
EXPECT_FALSE(web_app_scope->IsInScope(GURL("https://another.com/")));
}
TEST_F(WebAppScopeTest, LongerScopeWins) {
const GURL scope1("https://example.com/");
const GURL scope2("https://example.com/app/");
webapps::AppId app_id1 = InstallWebAppWithScope(scope1);
webapps::AppId app_id2 = InstallWebAppWithScope(scope2);
std::optional<WebAppScope> web_app_scope1 =
registrar().GetEffectiveScope(app_id1);
ASSERT_TRUE(web_app_scope1);
std::optional<WebAppScope> web_app_scope2 =
registrar().GetEffectiveScope(app_id2);
ASSERT_TRUE(web_app_scope2);
EXPECT_GT(
web_app_scope2->GetScopeScore(GURL("https://example.com/app/index.html")),
web_app_scope1->GetScopeScore(
GURL("https://example.com/app/index.html")));
}
TEST_F(WebAppScopeTest, GetScopeScoreBasic) {
const GURL scope("https://example.com/");
webapps::AppId app_id = InstallWebAppWithScope(scope);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://example.com/")), 0);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://example.com/path")), 0);
EXPECT_EQ(web_app_scope->GetScopeScore(GURL("https://example.org/")), 0);
}
TEST_F(WebAppScopeTest, GetScopeScoreWithSubdir) {
const GURL scope("https://example.com/subdir/");
webapps::AppId app_id = InstallWebAppWithScope(scope);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://example.com/subdir/")),
0);
EXPECT_GT(
web_app_scope->GetScopeScore(GURL("https://example.com/subdir/path")), 0);
EXPECT_EQ(web_app_scope->GetScopeScore(GURL("https://example.com/")), 0);
EXPECT_EQ(web_app_scope->GetScopeScore(GURL("https://example.com/path")), 0);
}
TEST_F(WebAppScopeTest, GetScopeScoreWithScopeExtensions) {
const GURL scope("https://example.com/");
const std::vector<ScopeExtensionInfo> scope_extensions = {
ScopeExtensionInfo::CreateForOrigin(
url::Origin::Create(GURL("https://example.org"))),
ScopeExtensionInfo::CreateForOrigin(
url::Origin::Create(GURL("https://example.net")),
/*has_origin_wildcard=*/true)};
webapps::AppId app_id =
InstallWebAppWithScopeExtensions(scope, scope_extensions);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://example.com/")), 0);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://example.org/")), 0);
EXPECT_GT(web_app_scope->GetScopeScore(GURL("https://sub.example.net/")), 0);
EXPECT_EQ(web_app_scope->GetScopeScore(GURL("https://another.com/")), 0);
}
TEST_F(WebAppScopeTest, GetScopeScoreExcludeScopeExtensions) {
const GURL scope("https://example.com/");
const std::vector<ScopeExtensionInfo> scope_extensions = {
ScopeExtensionInfo::CreateForOrigin(
url::Origin::Create(GURL("https://example.org")))};
webapps::AppId app_id =
InstallWebAppWithScopeExtensions(scope, scope_extensions);
std::optional<WebAppScope> web_app_scope =
registrar().GetEffectiveScope(app_id);
ASSERT_TRUE(web_app_scope);
EXPECT_EQ(web_app_scope->GetScopeScore(
GURL("https://example.org/"),
WebAppScopeScoreOptions{.exclude_scope_extensions = true}),
0);
EXPECT_GT(web_app_scope->GetScopeScore(
GURL("https://example.org/"),
WebAppScopeScoreOptions{.exclude_scope_extensions = false}),
0);
}
} // namespace
} // namespace web_app