blob: 59fa3a2c15ba08afb145dfea5969669836d66dd8 [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 "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/test/test_extension_dir.h"
namespace extensions {
class DelayedSettingChangeTest
: public ExtensionBrowserTest,
public testing::WithParamInterface<std::tuple<std::string, bool>> {
protected:
const Extension* InstallTestExtension(mojom::ManifestLocation location) {
TestExtensionDir extension_dir;
extension_dir.WriteFile(
FILE_PATH_LITERAL("index.html"),
"<html><body><div>Just a Chrome Extension</div></body></html>");
extension_dir.WriteManifest(
base::Value::Dict()
.Set("manifest_version", 3)
.Set("name", "Test Managed Extension")
.Set("version", "1")
.Set("host_permissions", base::Value::List().Append("file://*/*")));
auto* extension = InstallExtensionWithSourceAndFlags(
extension_dir.Pack(), 1, location,
Extension::InitFromValueFlags::NO_FLAGS);
CHECK(extension);
return extension;
}
std::string GetScript_WarningMessageIsHidden(std::string_view setting) {
// NOTE: This relies on the layout of the chrome://extensions page, and may
// need to be updated if that layout changes.
static constexpr std::string_view kScriptTemplate =
R"((function() {
return document.
querySelector('extensions-manager').shadowRoot.
querySelector('extensions-detail-view').shadowRoot.
querySelector('%s').
querySelector('%s-warning').hidden;
})();)";
return base::StringPrintf(kScriptTemplate, setting.data(), setting.data());
}
std::string GetScript_SwitchIsOn(std::string_view setting) {
// NOTE: This relies on the layout of the chrome://extensions page, and may
// need to be updated if that layout changes.
static constexpr std::string_view kScriptTemplate =
R"((function() {
return document.
querySelector('extensions-manager').shadowRoot.
querySelector('extensions-detail-view').shadowRoot.
querySelector('%s').shadowRoot.
querySelector('cr-toggle').ariaPressed;
})();)";
return base::StringPrintf(kScriptTemplate, setting.data());
}
std::string GetScript_ClickSwitch(std::string_view setting) {
// NOTE: This relies on the layout of the chrome://extensions page, and may
// need to be updated if that layout changes.
static constexpr std::string_view kScriptTemplate =
R"((function() {
document.
querySelector('extensions-manager').shadowRoot.
querySelector('extensions-detail-view').shadowRoot.
querySelector('%s').shadowRoot.
querySelector('cr-toggle').click();
})();)";
return base::StringPrintf(kScriptTemplate, setting.data());
}
};
INSTANTIATE_TEST_SUITE_P(
DelayedSetting,
DelayedSettingChangeTest,
::testing::Combine(::testing::Values("#allow-incognito",
"#allow-on-file-urls"),
::testing::Bool()));
IN_PROC_BROWSER_TEST_P(DelayedSettingChangeTest,
DetailsPageOfManagedExtension) {
scoped_refptr<const Extension> extension =
InstallTestExtension(mojom::ManifestLocation::kExternalPolicy);
ASSERT_TRUE(extension.get());
auto [setting_under_test, initial_value] = GetParam();
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
if (setting_under_test == "#allow-incognito") {
extension_prefs->SetIsIncognitoEnabled(extension->id(), initial_value);
} else {
extension_prefs->SetAllowFileAccess(extension->id(), initial_value);
}
// Go to the extension details page.
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), GURL("chrome://extensions?id=" + extension->id())));
content::WebContents* tab = GetActiveWebContents();
EXPECT_TRUE(content::WaitForLoadStop(tab));
// Initial state after installation.
EXPECT_EQ(true, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
EXPECT_EQ(initial_value,
content::EvalJs(tab, GetScript_SwitchIsOn(setting_under_test))
.ExtractString() == "true");
// Change the value of the setting.
EXPECT_EQ(true,
content::ExecJs(tab, GetScript_ClickSwitch(setting_under_test)));
// The warning message should now be visible.
EXPECT_EQ(false, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
// The status of the switch should have changed.
EXPECT_NE(initial_value,
content::EvalJs(tab, GetScript_SwitchIsOn(setting_under_test))
.ExtractString() == "true");
}
IN_PROC_BROWSER_TEST_P(DelayedSettingChangeTest, DetailsPageOfOtherExtension) {
scoped_refptr<const Extension> managed_extension =
InstallTestExtension(mojom::ManifestLocation::kExternalPolicy);
ASSERT_TRUE(managed_extension.get());
scoped_refptr<const Extension> second_extension =
InstallTestExtension(mojom::ManifestLocation::kExternalPolicy);
ASSERT_TRUE(second_extension.get());
ASSERT_NE(managed_extension->id(), second_extension->id());
auto [setting_under_test, initial_value] = GetParam();
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
if (setting_under_test == "#allow-incognito") {
extension_prefs->SetIsIncognitoEnabled(managed_extension->id(),
initial_value);
} else {
extension_prefs->SetAllowFileAccess(managed_extension->id(), initial_value);
}
// Go to the managed extension details page.
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), GURL("chrome://extensions?id=" + managed_extension->id())));
content::WebContents* tab = GetActiveWebContents();
EXPECT_TRUE(content::WaitForLoadStop(tab));
// Initial state after installation.
EXPECT_EQ(true, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
EXPECT_EQ(initial_value,
content::EvalJs(tab, GetScript_SwitchIsOn(setting_under_test))
.ExtractString() == "true");
// Change the value of the setting.
EXPECT_EQ(true,
content::ExecJs(tab, GetScript_ClickSwitch(setting_under_test)));
// The warning message should now be visible.
EXPECT_EQ(false, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
// Go to the 2nd extension details page.
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), GURL("chrome://extensions?id=" + second_extension->id())));
tab = GetActiveWebContents();
EXPECT_TRUE(content::WaitForLoadStop(tab));
EXPECT_EQ(true, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
// Return to the managed extension details page.
ASSERT_TRUE(ui_test_utils::NavigateToURL(
browser(), GURL("chrome://extensions?id=" + managed_extension->id())));
tab = GetActiveWebContents();
EXPECT_TRUE(content::WaitForLoadStop(tab));
// The warning message for the managed extension should be visible.
EXPECT_EQ(false, content::EvalJs(tab, GetScript_WarningMessageIsHidden(
setting_under_test)));
// The status of the switch should have changed.
EXPECT_NE(initial_value,
content::EvalJs(tab, GetScript_SwitchIsOn(setting_under_test))
.ExtractString() == "true");
}
} // namespace extensions