Commit 71f516df authored by Oksana Zhuravlova's avatar Oksana Zhuravlova Committed by Commit Bot

Revert "Changes to Webstore Private API to support child extension installation"

This reverts commit 99ffda8e.

Reason for revert: browser_tests failing on https://ci.chromium.org/p/chromium/builders/ci/Linux%20Chromium%20OS%20ASan%20LSan%20Tests%20%281%29/37129 and https://ci.chromium.org/p/chromium/builders/ci/Linux%20ChromiumOS%20MSan%20Tests/18174

Original change's description:
> Changes to Webstore Private API to support child extension installation
> 
> These changes are required in order to prompt a child user to get
> parent permission when they attempt to install an extension in the
> Chrome Webstore.
> 
> This CL also enables the feature by default.
> 
> Bug: 957832
> Change-Id: I3a2011b418e31dd491fd35e37d976b492eef197b
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2079620
> Commit-Queue: Dan S <danan@chromium.org>
> Reviewed-by: Karan Bhatia <karandeepb@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#749436}

TBR=karandeepb@chromium.org,danan@chromium.org

Change-Id: If262ccd3dad279dc60e849f9780e340b18d7384c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 957832
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2100891Reviewed-by: default avatarOksana Zhuravlova <oksamyt@chromium.org>
Commit-Queue: Oksana Zhuravlova <oksamyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#749726}
parent 7ac80a55
......@@ -52,11 +52,9 @@
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
// flag to #if defined(OS_CHROMEOS)
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
#endif
using safe_browsing::SafeBrowsingNavigationObserverManager;
......@@ -157,16 +155,6 @@ const char kIncognitoError[] =
const char kEphemeralAppLaunchingNotSupported[] =
"Ephemeral launching of apps is no longer supported.";
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// Note that the following error doesn't mean an incorrect password was entered,
// nor that the parent permisison request was canceled by the user, but rather
// that the Parent permission request after credential entry and acceptance
// failed due to a either network connection error or some unsatisfied invariant
// that prevented the request from completing.
const char kWebstoreParentPermissionFailedError[] =
"Parent permission request failed";
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
// The number of user gestures to trace back for the referrer chain.
const int kExtensionReferrerUserGestureLimit = 2;
......@@ -286,11 +274,12 @@ WebstorePrivateApi::PopApprovalForTesting(Profile* profile,
}
WebstorePrivateBeginInstallWithManifest3Function::
WebstorePrivateBeginInstallWithManifest3Function()
: chrome_details_(this) {}
WebstorePrivateBeginInstallWithManifest3Function() : chrome_details_(this) {
}
WebstorePrivateBeginInstallWithManifest3Function::
~WebstorePrivateBeginInstallWithManifest3Function() = default;
~WebstorePrivateBeginInstallWithManifest3Function() {
}
ExtensionFunction::ResponseAction
WebstorePrivateBeginInstallWithManifest3Function::Run() {
......@@ -433,18 +422,11 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
: ExtensionInstallPrompt::EXTENSION_PENDING_REQUEST_PROMPT),
ExtensionInstallPrompt::GetDefaultShowDialogCallback());
} else {
auto prompt = std::make_unique<ExtensionInstallPrompt::Prompt>(
ExtensionInstallPrompt::INSTALL_PROMPT);
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
prompt->set_user_is_child(profile->IsChild());
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
install_prompt_->ShowDialog(
base::BindRepeating(&WebstorePrivateBeginInstallWithManifest3Function::
OnInstallPromptDone,
this),
dummy_extension_.get(), &icon_, std::move(prompt),
dummy_extension_.get(), &icon_,
ExtensionInstallPrompt::GetDefaultShowDialogCallback());
}
// Control flow finishes up in OnInstallPromptDone or OnRequestPromptDone.
......@@ -463,120 +445,11 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseFailure(
Release();
}
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
void WebstorePrivateBeginInstallWithManifest3Function::OnParentPermissionDone(
std::unique_ptr<ParentPermissionDialog> dialog,
ParentPermissionDialog::Result result) {
switch (result) {
case ParentPermissionDialog::Result::kParentPermissionReceived:
OnParentPermissionReceived();
break;
case ParentPermissionDialog::Result::kParentPermissionCanceled:
OnParentPermissionCanceled();
break;
case ParentPermissionDialog::Result::kParentPermissionFailed:
OnParentPermissionFailed();
break;
}
}
void WebstorePrivateBeginInstallWithManifest3Function::
OnParentPermissionReceived() {
SupervisedUserService* service =
SupervisedUserServiceFactory::GetForProfile(chrome_details_.GetProfile());
service->AddExtensionApproval(*dummy_extension_);
HandleInstallProceed();
Release(); // Matches the AddRef in Run().
}
void WebstorePrivateBeginInstallWithManifest3Function::
OnParentPermissionCanceled() {
if (test_webstore_installer_delegate) {
test_webstore_installer_delegate->OnExtensionInstallFailure(
dummy_extension_->id(), kWebstoreParentPermissionFailedError,
WebstoreInstaller::FailureReason::FAILURE_REASON_CANCELLED);
}
HandleInstallAbort(true /* user_initiated */);
Release(); // Matches the AddRef in Run().
}
void WebstorePrivateBeginInstallWithManifest3Function::
OnParentPermissionFailed() {
if (test_webstore_installer_delegate) {
test_webstore_installer_delegate->OnExtensionInstallFailure(
dummy_extension_->id(), kWebstoreParentPermissionFailedError,
WebstoreInstaller::FailureReason::FAILURE_REASON_OTHER);
}
Respond(BuildResponse(api::webstore_private::RESULT_UNKNOWN_ERROR,
kWebstoreParentPermissionFailedError));
Release(); // Matches the AddRef in Run().
}
bool WebstorePrivateBeginInstallWithManifest3Function::
PromptForParentApproval() {
Profile* profile = chrome_details_.GetProfile();
DCHECK(profile->IsChild());
content::WebContents* web_contents = GetSenderWebContents();
if (!web_contents) {
// The browser window has gone away.
Respond(BuildResponse(api::webstore_private::RESULT_USER_CANCELLED,
kWebstoreUserCancelledError));
return false;
}
bool reprompt_after_incorrect_credential = true;
// If we are in a test, then we don't reprompt after an incorrect
// credential because that, combined with the auto-confirm, would
// result in an infinite invalid password / reprompt loop, and
// eventually a test timeout.
if (test_webstore_installer_delegate)
reprompt_after_incorrect_credential = false;
auto parent_permission_dialog =
std::make_unique<ParentPermissionDialog>(profile);
parent_permission_dialog->set_reprompt_after_incorrect_credential(
reprompt_after_incorrect_credential);
// Cache a pointer to the dialog so we can show it after we transfer
// ownership to the callback.
ParentPermissionDialog* dialog_ptr = parent_permission_dialog.get();
ParentPermissionDialog::DoneCallback done_callback = base::BindOnce(
&WebstorePrivateBeginInstallWithManifest3Function::OnParentPermissionDone,
this, std::move(parent_permission_dialog));
dialog_ptr->ShowPromptForExtensionInstallation(
web_contents, dummy_extension_.get(), icon_, std::move(done_callback));
return true;
}
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
void WebstorePrivateBeginInstallWithManifest3Function::OnInstallPromptDone(
ExtensionInstallPrompt::Result result) {
switch (result) {
case ExtensionInstallPrompt::Result::ACCEPTED:
case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED: {
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// Handle parent permission for child accounts on ChromeOS.
Profile* profile = chrome_details_.GetProfile();
if (profile->IsChild()) {
if (PromptForParentApproval()) {
// If are showing parent permission dialog, return instead of
// break, so that we don't release the ref below.
return;
} else {
// An error occurred in the dialog setup, so release and abort.
HandleInstallAbort(false /* user_initiated */);
break;
}
}
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
HandleInstallProceed();
break;
}
......@@ -660,8 +533,7 @@ void WebstorePrivateBeginInstallWithManifest3Function::HandleInstallAbort(
ExtensionFunction::ResponseValue
WebstorePrivateBeginInstallWithManifest3Function::BuildResponse(
api::webstore_private::Result result,
const std::string& error) {
api::webstore_private::Result result, const std::string& error) {
if (result != api::webstore_private::RESULT_SUCCESS)
return ErrorWithArguments(CreateResults(result), error);
......
......@@ -14,18 +14,11 @@
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/webstore_install_helper.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/extensions/api/webstore_private.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "extensions/browser/extension_function.h"
#include "third_party/skia/include/core/SkBitmap.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
// flag to #if defined(OS_CHROMEOS)
#include "chrome/browser/ui/supervised_user/parent_permission_dialog.h"
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
namespace content {
class GpuFeatureChecker;
}
......@@ -75,16 +68,6 @@ class WebstorePrivateBeginInstallWithManifest3Function
InstallHelperResultCode result,
const std::string& error_message) override;
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
void OnParentPermissionDone(std::unique_ptr<ParentPermissionDialog> dialog,
ParentPermissionDialog::Result result);
void OnParentPermissionReceived();
void OnParentPermissionCanceled();
void OnParentPermissionFailed();
// Returns true if the parental approval prompt was shown, false if there was
// an error showing it.
bool PromptForParentApproval();
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
void OnRequestPromptDone(ExtensionInstallPrompt::Result result);
......
......@@ -42,18 +42,8 @@
#include "ui/gl/gl_switches.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
// flag to #if defined(OS_CHROMEOS)
#include "chrome/browser/supervised_user/logged_in_user_mixin.h"
#include "chrome/browser/supervised_user/supervised_user_constants.h"
#include "chrome/browser/supervised_user/supervised_user_features.h"
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
#include "chrome/browser/ui/supervised_user/parent_permission_dialog.h"
#include "chrome/common/pref_names.h"
#include "components/account_id/account_id.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "extensions/common/extension_builder.h"
#if defined(OS_CHROMEOS)
#include "chromeos/constants/chromeos_switches.h"
......@@ -89,7 +79,6 @@ class WebstoreInstallListener : public WebstoreInstaller::Delegate {
received_failure_ = true;
id_ = id;
error_ = error;
last_failure_reason_ = reason;
if (waiting_) {
waiting_ = false;
......@@ -105,17 +94,12 @@ class WebstoreInstallListener : public WebstoreInstaller::Delegate {
content::RunMessageLoop();
}
bool received_success() const { return received_success_; }
bool received_failure() const { return received_failure_; }
const std::string& id() const { return id_; }
WebstoreInstaller::FailureReason last_failure_reason() {
return last_failure_reason_;
}
private:
bool received_failure_;
bool received_success_;
bool waiting_;
WebstoreInstaller::FailureReason last_failure_reason_;
std::string id_;
std::string error_;
};
......@@ -388,23 +372,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, EmptyCrx) {
}
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
static constexpr char kTestChildEmail[] = "test_child_user@google.com";
static constexpr char kTestChildGaiaId[] = "8u8tuw09sufncmnaos";
class ExtensionWebstorePrivateApiTestChild
: public ExtensionWebstorePrivateApiTest {
public:
ExtensionWebstorePrivateApiTestChild()
: embedded_test_server_(std::make_unique<net::EmbeddedTestServer>()),
logged_in_user_mixin_(
&mixin_host_,
chromeos::LoggedInUserMixin::LogInType::kChild,
embedded_test_server_.get(),
this,
true /* should_launch_browser */,
base::Optional<AccountId>(
AccountId::FromUserEmailGaiaId(kTestChildEmail,
kTestChildGaiaId))) {
logged_in_user_mixin_(&mixin_host_,
chromeos::LoggedInUserMixin::LogInType::kChild,
embedded_test_server_.get(),
this) {
// Suppress regular user login to enable child user login.
set_chromeos_user_ = false;
}
......@@ -446,40 +422,10 @@ class ExtensionWebstorePrivateApiTestChild
browser_main_parts);
}
void InitializeFamilyData() {
// Set up the child user's custodians (i.e. parents).
ASSERT_TRUE(browser());
PrefService* prefs = browser()->profile()->GetPrefs();
prefs->SetString(prefs::kSupervisedUserCustodianEmail,
"test_parent_0@google.com");
prefs->SetString(prefs::kSupervisedUserCustodianObfuscatedGaiaId,
"239029320");
prefs->SetString(prefs::kSupervisedUserSecondCustodianEmail,
"test_parent_1@google.com");
prefs->SetString(prefs::kSupervisedUserSecondCustodianObfuscatedGaiaId,
"85948533");
// Set up the identity test environment, which provides fake
// OAuth refresh tokens.
identity_test_env_ = std::make_unique<signin::IdentityTestEnvironment>();
identity_test_env_->MakeAccountAvailable(kTestChildEmail);
identity_test_env_->SetPrimaryAccount(kTestChildEmail);
identity_test_env_->SetRefreshTokenForPrimaryAccount();
identity_test_env_->SetAutomaticIssueOfAccessTokens(true);
ParentPermissionDialog::SetFakeIdentityManagerForTesting(
identity_test_env_->identity_manager());
}
void SetUpOnMainThread() override {
mixin_host_.SetUpOnMainThread();
logged_in_user_mixin_.LogInUser(true /* issue_any_scope_token */);
ExtensionWebstorePrivateApiTest::SetUpOnMainThread();
InitializeFamilyData();
SupervisedUserService* service =
SupervisedUserServiceFactory::GetForProfile(profile());
service->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(
true);
logged_in_user_mixin_.LogInUser(true /*issue_any_scope_token*/);
}
void TearDownOnMainThread() override {
......@@ -497,114 +443,22 @@ class ExtensionWebstorePrivateApiTestChild
ExtensionWebstorePrivateApiTest::TearDown();
}
chromeos::LoggedInUserMixin* GetLoggedInUserMixin() {
return &logged_in_user_mixin_;
}
void SetNextReAuthStatus(
const GaiaAuthConsumer::ReAuthProofTokenStatus next_status) {
GetLoggedInUserMixin()
->GetFakeGaiaMixin()
->fake_gaia()
->SetNextReAuthStatus(next_status);
}
private:
// Replicate what MixinBasedInProcessBrowserTest does since inheriting from
// that class is inconvenient here.
InProcessBrowserTestMixinHost mixin_host_;
// Create another embedded test server to avoid starting the same one twice.
std::unique_ptr<net::EmbeddedTestServer> embedded_test_server_;
std::unique_ptr<signin::IdentityTestEnvironment> identity_test_env_;
chromeos::LoggedInUserMixin logged_in_user_mixin_;
};
class ExtensionWebstorePrivateApiTestChildInstallDisabled
: public ExtensionWebstorePrivateApiTestChild {
public:
ExtensionWebstorePrivateApiTestChildInstallDisabled() {
feature_list_.InitWithFeatures(
{}, {supervised_users::kSupervisedUserInitiatedExtensionInstall});
}
private:
base::test::ScopedFeatureList feature_list_;
};
// Tests that extension installation is blocked for child accounts when
// the feature flag is disabled.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallDisabled,
InstallBlocked) {
ASSERT_TRUE(RunInstallTest("install_blocked_child.html", "app.crx"));
}
static constexpr char kTestAppId[] = "iladmdjkfniedhfhcfoefgojhgaiaccc";
static constexpr char kTestAppVersion[] = "0.1";
// Tests fixture for various cases of installation for child accounts
// when the feature flag is enabled.
class ExtensionWebstorePrivateApiTestChildInstallEnabled
: public ExtensionWebstorePrivateApiTestChild {
public:
ExtensionWebstorePrivateApiTestChildInstallEnabled() {
feature_list_.InitWithFeatures(
{supervised_users::kSupervisedUserInitiatedExtensionInstall}, {});
}
private:
base::test::ScopedFeatureList feature_list_;
chromeos::LoggedInUserMixin logged_in_user_mixin_;
};
// Tests install for a child when parent permission is granted.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallEnabled,
ParentPermissionGranted) {
WebstoreInstallListener listener;
WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
// Tell the Reauth API client to return a success for the next reauth
// request.
SetNextReAuthStatus(GaiaAuthConsumer::ReAuthProofTokenStatus::kSuccess);
SetAutoConfirmParentPermissionDialogForTest(
::internal::ParentPermissionDialogViewResult::Status::kAccepted);
ASSERT_TRUE(RunInstallTest("install_child.html", "app.crx"));
listener.Wait();
ASSERT_TRUE(listener.received_success());
ASSERT_EQ(kTestAppId, listener.id());
scoped_refptr<const Extension> extension =
extensions::ExtensionBuilder("test extension")
.SetID(kTestAppId)
.SetVersion(kTestAppVersion)
.Build();
SupervisedUserService* service =
SupervisedUserServiceFactory::GetForProfile(profile());
ASSERT_TRUE(service->IsExtensionAllowed(*extension));
}
// Tests no install occurs for a child when the parent permission
// dialog is canceled.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallEnabled,
ParentPermissionCanceled) {
WebstoreInstallListener listener;
WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
SetAutoConfirmParentPermissionDialogForTest(
::internal::ParentPermissionDialogViewResult::Status::kCanceled);
ASSERT_TRUE(RunInstallTest("install_cancel_child.html", "app.crx"));
listener.Wait();
ASSERT_TRUE(listener.received_failure());
ASSERT_EQ(kTestAppId, listener.id());
ASSERT_EQ(listener.last_failure_reason(),
WebstoreInstaller::FailureReason::FAILURE_REASON_CANCELLED);
scoped_refptr<const Extension> extension =
extensions::ExtensionBuilder("test extension")
.SetID(kTestAppId)
.SetVersion(kTestAppVersion)
.Build();
SupervisedUserService* service =
SupervisedUserServiceFactory::GetForProfile(profile());
ASSERT_FALSE(service->IsExtensionAllowed(*extension));
// Tests that extension installation is blocked for child accounts, and
// attempting to do so produces a special error code.
// Note: This will have to be updated when we enable child-initiated installs.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChild, InstallBlocked) {
ASSERT_TRUE(browser());
ASSERT_TRUE(RunInstallTest("begin_install_fail_child.html", "extension.crx"));
}
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
......
......@@ -11,5 +11,5 @@ const base::Feature kSupervisedUserIframeFilter{
const base::Feature kSupervisedUserInitiatedExtensionInstall{
"SupervisedUserInitiatedExtensionInstall",
base::FEATURE_ENABLED_BY_DEFAULT};
base::FEATURE_DISABLED_BY_DEFAULT};
}
......@@ -7,12 +7,12 @@
<script>
runTests([
function installBlockedChild() {
function beginInstall() {
var manifest = getManifest();
var expectedError =
"Apps and extensions can only be modified by the manager (test_parent_0@google.com)."
"Apps and extensions can only be modified by the manager ()."
chrome.webstorePrivate.beginInstallWithManifest3(
{id: appId, manifest: manifest},
{id: extensionId, manifest: manifest},
callbackFail(expectedError, function(result) {
assertEq("blocked_for_child_account", result);
}));
......
<!--
* Copyright 2020 The Chromium Authors. All rights reserved. Use of this
* source code is governed by a BSD-style license that can be found in the
* LICENSE file.
-->
<script src="common.js"></script>
<script>
runTests([
function installCanceledChild() {
var manifest = getManifest();
chrome.webstorePrivate.beginInstallWithManifest3(
{id: appId, manifest: manifest},
function(result) {
assertEq(result, "user_cancelled");
succeed();
});
},
]);
</script>
<!--
* Copyright 2020 The Chromium Authors. All rights reserved. Use of this
* source code is governed by a BSD-style license that can be found in the
* LICENSE file.
-->
<script src="common.js"></script>
<script>
runTests([
function installChild() {
var manifest = getManifest();
chrome.webstorePrivate.beginInstallWithManifest3(
{id: appId, manifest: manifest},
callbackPass(function(result) {
assertEq("", result);
// Complete the installation
chrome.webstorePrivate.completeInstall(appId, callbackPass());
}));
},
]);
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment