Skip to content

Commit

Permalink
[M113] Cherry-pick a fix for shutdown crash
Browse files Browse the repository at this point in the history
The shutdown crash is caused by the code that removes the extension disable reason from the user who is not supervised any more.
The disable reason is incorrectly removed for supervised users
during the SupervisedUserService shutdown and cleanup.

The changes applied to the original cl in order to compile on M113:
1) Use Profile:IsChild() instead of SuperviseUserService::IsSubjectToParentalControls() to check whether
user is supervised, because later is not available in M113.

3) Use prefs name from chrome/common, because kSupervisedUserId
was not moved yet.

Tested manually on M113 branch. Confirmed that crash is not being
reported anymore.

---------------------------------------------------

Reland "Enable supervised_user_extension_browsertest.cc and introduce the SupervisionMixin that replaces LoggedInUserMixin."

This is a reland of commit 101042b

The diff against reverted change is that the preferences regarding the supervised user profile are set directly, rather than TestingProfile.

Original change's description:
> Enable supervised_user_extension_browsertest.cc and introduce the SupervisedUserMixin that replaces LoggedInUserMixin.
>
> Bug: b:276874936, 1218633
> Change-Id: Iea0a1255bf20265ab9411227429138f3433bf186
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4427809
> Reviewed-by: Colin Blundell <blundell@chromium.org>
> Commit-Queue: Tomek Jurkiewicz <tju@google.com>
> Reviewed-by: Nohemi Fernandez <fernandex@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1137145}

(cherry picked from commit 19f06e4)

Bug: 1435569
Change-Id: I067f86bd989bca0da54a64b5c0dee0478c883679
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4492183
Commit-Queue: Tomek Jurkiewicz <tju@google.com>
Reviewed-by: Finnur Thorarinsson <finnur@chromium.org>
Reviewed-by: Nohemi Fernandez <fernandex@chromium.org>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1138312}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4533335
Commit-Queue: Aga Wronska <agawronska@chromium.org>
Reviewed-by: Courtney Wong <courtneywong@chromium.org>
Owners-Override: Prudhvikumar Bommana <pbommana@google.com>
Cr-Commit-Position: refs/branch-heads/5672@{#1222}
Cr-Branched-From: 5f2a724-refs/heads/main@{#1121455}
  • Loading branch information
Aga Wronska authored and Chromium LUCI CQ committed May 17, 2023
1 parent 310cab0 commit 67bd471
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 53 deletions.
13 changes: 1 addition & 12 deletions chrome/browser/extensions/extension_service.cc
Expand Up @@ -127,11 +127,6 @@
#include "storage/browser/file_system/file_system_context.h"
#endif

#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)

using content::BrowserContext;
using content::BrowserThread;
using extensions::mojom::ManifestLocation;
Expand Down Expand Up @@ -1227,13 +1222,7 @@ void ExtensionService::CheckManagementPolicy() {

// If this profile is not supervised, then remove any supervised user
// related disable reasons.
bool extensions_permissions_enabled = true;
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
extensions_permissions_enabled =
SupervisedUserServiceFactory::GetForProfile(profile())
->AreExtensionsPermissionsEnabled();
#endif
if (extensions_permissions_enabled) {
if (!profile()->IsChild()) {
disable_reasons &= (~disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
}

Expand Down
Expand Up @@ -3,14 +3,11 @@
// found in the LICENSE file.

#include "base/files/file_path.h"
#include "chrome/browser/ash/login/test/device_state_mixin.h"
#include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_test_util.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/supervised_user/supervision_mixin.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_launcher.h"
#include "extensions/browser/disable_reason.h"
Expand All @@ -19,21 +16,14 @@
#include "extensions/common/extension.h"

namespace {

constexpr char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";

}
} // namespace

namespace extensions {

// Tests for the interaction between supervised users and extensions.
class SupervisedUserExtensionTest : public ExtensionBrowserTest {
public:
SupervisedUserExtensionTest() {
// Suppress regular user login to enable child user login.
set_chromeos_user_ = false;
}

// We have to essentially replicate what MixinBasedInProcessBrowserTest does
// here because ExtensionBrowserTest doesn't inherit from that class.
void SetUp() override {
Expand Down Expand Up @@ -69,7 +59,6 @@ class SupervisedUserExtensionTest : public ExtensionBrowserTest {

void SetUpOnMainThread() override {
mixin_host_.SetUpOnMainThread();
logged_in_user_mixin_.LogInUser();
ExtensionBrowserTest::SetUpOnMainThread();
}

Expand All @@ -89,10 +78,6 @@ class SupervisedUserExtensionTest : public ExtensionBrowserTest {
}

protected:
SupervisedUserService* GetSupervisedUserService() {
return SupervisedUserServiceFactory::GetForProfile(profile());
}

bool IsDisabledForCustodianApproval(const std::string& extension_id) {
ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
return extension_prefs->HasDisableReason(
Expand All @@ -102,17 +87,13 @@ class SupervisedUserExtensionTest : public ExtensionBrowserTest {

private:
InProcessBrowserTestMixinHost mixin_host_;

ash::DeviceStateMixin device_state_{
&mixin_host_,
ash::DeviceStateMixin::State::OOBE_COMPLETED_CONSUMER_OWNED};
// We want to log in as child user for all of the PRE tests, and regular user
// otherwise.
ash::LoggedInUserMixin logged_in_user_mixin_{
&mixin_host_,
content::IsPreTest() ? ash::LoggedInUserMixin::LogInType::kChild
: ash::LoggedInUserMixin::LogInType::kRegular,
embedded_test_server(), this};
supervised_user::SupervisionMixin supervision_mixin_{
mixin_host_,
this,
{.account_type =
content::IsPreTest()
? supervised_user::SupervisionMixin::AccountType::kSupervised
: supervised_user::SupervisionMixin::AccountType::kRegular}};
};

// Removing supervision should also remove associated disable reasons, such as
Expand All @@ -123,7 +104,7 @@ IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,
supervised_user_test_util::
SetSupervisedUserExtensionsMayRequestPermissionsPref(profile(), true);

EXPECT_TRUE(profile()->IsChild());
ASSERT_TRUE(profile()->IsChild());

base::FilePath path = test_data_dir_.AppendASCII("good.crx");
EXPECT_FALSE(LoadExtension(path));
Expand All @@ -139,14 +120,19 @@ IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,

IN_PROC_BROWSER_TEST_F(SupervisedUserExtensionTest,
RemovingSupervisionCustodianApprovalRequired) {
EXPECT_FALSE(profile()->IsChild());
ASSERT_FALSE(profile()->IsChild());

// The extension should still be installed since we are sharing the same data
// directory as the PRE test.
const Extension* extension =
extension_registry()->GetInstalledExtension(kGoodCrxId);
EXPECT_TRUE(extension);

// The extension should be enabled now after removing supervision.
EXPECT_TRUE(extension_registry()->enabled_extensions().Contains(kGoodCrxId));
EXPECT_FALSE(
extension_registry()->disabled_extensions().Contains(kGoodCrxId));

EXPECT_FALSE(IsDisabledForCustodianApproval(kGoodCrxId));
}

Expand Down
33 changes: 23 additions & 10 deletions chrome/test/BUILD.gn
Expand Up @@ -3691,22 +3691,27 @@ if (!is_android) {
}

# TODO(https://crbug.com/1218633): Fix the mixin and enable tests on LaCrOS and desktop.
if (enable_supervised_users && is_chromeos_ash) {
sources += [
"../browser/supervised_user/permission_request_creator_mock.cc",
"../browser/supervised_user/permission_request_creator_mock.h",
"../browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc",
"../browser/supervised_user/supervised_user_regional_url_filter_browsertest.cc",
"../browser/supervised_user/supervised_user_service_browsertest.cc",
"../browser/supervised_user/supervised_user_url_filter_browsertest.cc",
]
if (enable_supervised_users) {
if (enable_extensions) {
sources += [
"../browser/supervised_user/supervised_user_extension_browsertest.cc",
"../browser/ui/views/supervised_user/extension_install_blocked_by_parent_dialog_browsertest.cc",
"../browser/ui/views/supervised_user/parent_permission_dialog_view_browsertest.cc",
]
}
if (is_chromeos_ash) {
sources += [
"../browser/supervised_user/permission_request_creator_mock.cc",
"../browser/supervised_user/permission_request_creator_mock.h",
"../browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc",
"../browser/supervised_user/supervised_user_regional_url_filter_browsertest.cc",
"../browser/supervised_user/supervised_user_service_browsertest.cc",
"../browser/supervised_user/supervised_user_url_filter_browsertest.cc",
]
if (enable_extensions) {
sources += [ "../browser/ui/views/supervised_user/parent_permission_dialog_view_browsertest.cc" ]
}
}

deps += [
"//chrome/browser/supervised_user:test_support",
"//components/supervised_user/core/browser",
Expand Down Expand Up @@ -9301,6 +9306,14 @@ if (!is_android) {
"permissions/permission_request_manager_test_api.cc",
"permissions/permission_request_manager_test_api.h",
]

if (enable_supervised_users) {
sources += [
"supervised_user/supervision_mixin.cc",
"supervised_user/supervision_mixin.h",
]
}

if (is_mac) {
sources += [
"../browser/ui/test/test_browser_dialog_mac.h",
Expand Down
1 change: 1 addition & 0 deletions chrome/test/supervised_user/OWNERS
@@ -0,0 +1 @@
file://components/supervised_user/OWNERS
136 changes: 136 additions & 0 deletions chrome/test/supervised_user/supervision_mixin.cc
@@ -0,0 +1,136 @@
// Copyright 2023 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/test/supervised_user/supervision_mixin.h"

#include <memory>

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/strings/string_piece.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/mixin_based_in_process_browser_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/signin/public/base/consent_level.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/signin/public/identity_manager/tribool.h"
#include "components/supervised_user/core/common/supervised_user_constants.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"

namespace supervised_user {

namespace {
void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
// Sets all required testing factories to have control over identity
// environment during test. Effectively, this substitutes the real identity
// environment with identity test environment, taking care to fulfill all
// required dependencies.
IdentityTestEnvironmentProfileAdaptor::
SetIdentityTestEnvironmentFactoriesOnBrowserContext(context);
}

bool IdentityManagerAlreadyHasPrimaryAccount(
signin::IdentityManager* identity_manager,
base::StringPiece email,
signin::ConsentLevel consent_level) {
if (!identity_manager->HasPrimaryAccount(consent_level)) {
return false;
}
CoreAccountInfo account_info =
identity_manager->GetPrimaryAccountInfo(consent_level);
return account_info.email == email;
}

void SetIsSupervisedProfile(Profile* profile, bool is_supervised_profile) {
if (is_supervised_profile) {
profile->GetPrefs()->SetString(prefs::kSupervisedUserId,
supervised_user::kChildAccountSUID);
} else {
profile->GetPrefs()->ClearPref(prefs::kSupervisedUserId);
}
}

} // namespace

SupervisionMixin::SupervisionMixin(
InProcessBrowserTestMixinHost& test_mixin_host,
InProcessBrowserTest* test_base)
: SupervisionMixin(test_mixin_host,
test_base,
SupervisionMixin::Options()) {}

SupervisionMixin::SupervisionMixin(
InProcessBrowserTestMixinHost& test_mixin_host,
InProcessBrowserTest* test_base,
const Options& options)
: InProcessBrowserTestMixin(&test_mixin_host),
test_base_(test_base),
fake_gaia_mixin_(&test_mixin_host),
consent_level_(options.consent_level),
email_(options.email),
account_type_(options.account_type) {}

SupervisionMixin::~SupervisionMixin() = default;

void SupervisionMixin::SetUpInProcessBrowserTestFixture() {
subscription_ =
BrowserContextDependencyManager::GetInstance()
->RegisterCreateServicesCallbackForTesting(
base::BindRepeating(&OnWillCreateBrowserContextServices));
}

void SupervisionMixin::SetUpOnMainThread() {
SetUpIdentityTestEnvironment();
LogInUser();
SetUpTestServer();
}

void SupervisionMixin::SetUpTestServer() {
// By default, browser tests block anything that doesn't go to localhost, so
// account.google.com requests would never reach fake GAIA server without
// this.
test_base_->host_resolver()->AddRule("*", "127.0.0.1");
}

void SupervisionMixin::SetUpIdentityTestEnvironment() {
adaptor_ = std::make_unique<IdentityTestEnvironmentProfileAdaptor>(
test_base_->browser()->profile());
}

void SupervisionMixin::LogInUser() {
if (!IdentityManagerAlreadyHasPrimaryAccount(
GetIdentityTestEnvironment()->identity_manager(), email_,
consent_level_)) {
// PRE_ tests intentionally leave accounts that are picked up by subsequent
// test runs.
AccountInfo account_info =
GetIdentityTestEnvironment()->MakePrimaryAccountAvailable(
email_, consent_level_);
CHECK(!account_info.account_id.empty());
}

GetIdentityTestEnvironment()->SetRefreshTokenForPrimaryAccount();
GetIdentityTestEnvironment()->SetAutomaticIssueOfAccessTokens(true);

SetIsSupervisedProfile(
test_base_->browser()->profile(),
/*is_supervised_profile=*/account_type_ == AccountType::kSupervised);
}

signin::IdentityTestEnvironment*
SupervisionMixin::GetIdentityTestEnvironment() {
CHECK(adaptor_->identity_test_env())
<< "Do not use before the environment is set up.";
return adaptor_->identity_test_env();
}

} // namespace supervised_user

0 comments on commit 67bd471

Please sign in to comment.