blob: cbca0b93cde90d843a9698d458b02fa44145dec7 [file] [log] [blame]
// 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/browser/supervised_user/supervised_user_browser_utils.h"
#include <string>
#include "base/check.h"
#include "base/feature_list.h"
#include "base/strings/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_selections.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/webui_url_constants.h"
#include "components/prefs/pref_service.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.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/tribool.h"
#include "components/supervised_user/core/browser/child_account_service.h"
#include "components/supervised_user/core/browser/family_link_user_capabilities.h"
#include "components/supervised_user/core/browser/supervised_user_service.h"
#include "components/supervised_user/core/common/features.h"
#include "components/supervised_user/core/common/pref_names.h"
#include "components/supervised_user/core/common/supervised_user_constants.h"
#include "components/url_matcher/url_util.h"
#include "content/public/browser/navigation_handle.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_urls.h"
#include "google_apis/gaia/core_account_id.h"
#include "url/url_constants.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_type.h"
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
#include "chrome/browser/supervised_user/supervised_user_verification_controller_client.h"
#include "chrome/browser/supervised_user/supervised_user_verification_page_blocked_sites.h"
#include "chrome/browser/supervised_user/supervised_user_verification_page_youtube.h"
#endif
namespace supervised_user {
bool IsSupportedChromeExtensionURL(const GURL& effective_url) {
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
static const char* const kCrxDownloadUrls[] = {
"https://clients2.googleusercontent.com/crx/blobs/",
"https://chrome.google.com/webstore/download/"};
// Chrome Webstore.
if (extension_urls::IsWebstoreDomain(
url_matcher::util::Normalize(effective_url))) {
return true;
}
// Allow webstore crx downloads. This applies to both extension installation
// and updates.
if (extension_urls::GetWebstoreUpdateUrl() ==
url_matcher::util::Normalize(effective_url)) {
return true;
}
// The actual CRX files are downloaded from other URLs. Allow them too.
// These URLs have https scheme.
if (!effective_url.SchemeIs(url::kHttpsScheme)) {
return false;
}
for (const char* crx_download_url_str : kCrxDownloadUrls) {
GURL crx_download_url(crx_download_url_str);
if (crx_download_url.host_piece() == effective_url.host_piece() &&
base::StartsWith(effective_url.path_piece(),
crx_download_url.path_piece(),
base::CompareCase::SENSITIVE)) {
return true;
}
}
return false;
#else
return false;
#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE)
}
bool SupervisedUserCanSkipExtensionParentApprovals(const Profile* profile) {
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
return profile->IsChild() &&
profile->GetPrefs()->GetBoolean(
prefs::kSkipParentApprovalToInstallExtensions);
#else
return false;
#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE)
}
bool AreExtensionsPermissionsEnabled(Profile* profile) {
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
return profile->IsChild();
#else
return false;
#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE)
}
bool ShouldContentSkipParentAllowlistFiltering(content::WebContents* contents) {
// Note that |contents| can be an inner WebContents. Get the outer most
// WebContents and check if it belongs to the EDUCoexistence login flow.
content::WebContents* outer_most_content =
contents->GetOutermostWebContents();
return outer_most_content->GetLastCommittedURL() ==
GURL(chrome::kChromeUIEDUCoexistenceLoginURLV2);
}
ProfileSelections BuildProfileSelectionsForRegularAndGuest() {
#if BUILDFLAG(IS_CHROMEOS)
return ProfileSelections::Builder()
.WithRegular(ProfileSelection::kRedirectedToOriginal)
.WithGuest(ProfileSelection::kOwnInstance)
// TODO(crbug.com/41488885): Check if this is needed for Ash Internals.
.WithAshInternals(ProfileSelection::kOriginalOnly)
.Build();
#else
// Do not create for Incognito profile.
return ProfileSelections::Builder()
.WithRegular(ProfileSelection::kOriginalOnly)
.WithGuest(ProfileSelection::kRedirectedToOriginal)
.Build();
#endif
}
std::string GetAccountGivenName(Profile& profile) {
signin::IdentityManager* identity_manager =
IdentityManagerFactory::GetForProfile(profile.GetOriginalProfile());
CHECK(identity_manager);
const CoreAccountInfo core_info =
identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
const AccountInfo account_info =
identity_manager->FindExtendedAccountInfo(core_info);
return account_info.given_name;
}
void AssertChildStatusOfTheUser(Profile* profile, bool is_child) {
#if BUILDFLAG(IS_CHROMEOS)
user_manager::User* user =
ash::ProfileHelper::Get()->GetUserByProfile(profile);
if (user && is_child != (user->GetType() == user_manager::UserType::kChild)) {
LOG(FATAL) << "User child flag has changed: " << is_child;
}
if (!user && ash::ProfileHelper::IsUserProfile(profile)) {
LOG(FATAL) << "User instance not found while setting child account flag.";
}
#endif
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
std::string CreateReauthenticationInterstitialForYouTube(
content::NavigationHandle& navigation_handle) {
content::WebContents* web_contents = navigation_handle.GetWebContents();
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
GURL request_url = navigation_handle.GetURL();
bool is_main_frame = navigation_handle.GetNavigatingFrameType() ==
content::FrameType::kPrimaryMainFrame;
std::unique_ptr<SupervisedUserVerificationPageForYouTube> blocking_page =
std::make_unique<SupervisedUserVerificationPageForYouTube>(
web_contents, profile->GetProfileUserName(), request_url,
ChildAccountServiceFactory::GetForProfile(profile),
navigation_handle.GetNextPageUkmSourceId(),
std::make_unique<SupervisedUserVerificationControllerClient>(
web_contents, profile->GetPrefs(),
g_browser_process->GetApplicationLocale(),
GURL(chrome::kChromeUINewTabURL), request_url),
is_main_frame);
std::string interstitial_html = blocking_page->GetHTMLContents();
security_interstitials::SecurityInterstitialTabHelper::AssociateBlockingPage(
&navigation_handle, std::move(blocking_page));
return interstitial_html;
}
std::string CreateReauthenticationInterstitialForBlockedSites(
content::NavigationHandle& navigation_handle,
FilteringBehaviorReason block_reason) {
content::WebContents* web_contents = navigation_handle.GetWebContents();
Profile* profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
supervised_user::SupervisedUserService* supervised_user_service =
SupervisedUserServiceFactory::GetForProfile(profile);
bool has_second_custodian =
supervised_user_service->GetSecondCustodian().has_value();
GURL request_url = navigation_handle.GetURL();
bool is_main_frame = navigation_handle.GetNavigatingFrameType() ==
content::FrameType::kPrimaryMainFrame;
std::unique_ptr<SupervisedUserVerificationPageForBlockedSites> blocking_page =
std::make_unique<SupervisedUserVerificationPageForBlockedSites>(
web_contents, profile->GetProfileUserName(), request_url,
ChildAccountServiceFactory::GetForProfile(profile),
std::make_unique<SupervisedUserVerificationControllerClient>(
web_contents, profile->GetPrefs(),
g_browser_process->GetApplicationLocale(),
GURL(chrome::kChromeUINewTabURL), request_url),
block_reason, is_main_frame, has_second_custodian);
std::string interstitial_html = blocking_page->GetHTMLContents();
security_interstitials::SecurityInterstitialTabHelper::AssociateBlockingPage(
&navigation_handle, std::move(blocking_page));
return interstitial_html;
}
#endif
} // namespace supervised_user