chromium/chrome/browser/policy/extension_force_install_mixin.cc

// Copyright 2020 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/policy/extension_force_install_mixin.h"

#include <stdint.h>

#include <atomic>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/check.h"
#include "base/check_op.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/important_file_writer.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "base/version.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "components/crx_file/crx_verifier.h"
#include "components/crx_file/id_util.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_service.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "extensions/browser/extension_creator.h"
#include "extensions/browser/extension_host_test_helper.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/pref_names.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/browser/updater/extension_downloader_test_helper.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/mojom/view_type.mojom.h"
#include "extensions/test/extension_test_message_listener.h"
#include "net/http/http_status_code.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/zlib/google/zip.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/login/test/device_state_mixin.h"
#include "chrome/browser/ash/login/test/scoped_policy_update.h"
#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h"
#include "chrome/browser/ash/policy/test_support/embedded_policy_test_server_mixin.h"
#include "components/policy/proto/chrome_device_policy.pb.h"
#endif

namespace {

// Name of the directory whose contents are served by the embedded test
// server.
constexpr char kServedDirName[] =;
// Hardcoded string value expected from the extension after extension is
// installed and it started executing.
constexpr char kReadyMessage[] =;
// Template for the file name of a served CRX file.
constexpr char kCrxFileNameTemplate[] =;
// Template for the file name of a served update manifest file.
constexpr char kUpdateManifestFileNameTemplate[] =;

// Implements waiting until the given extension appears in the
// force-installation pref.
class ForceInstallPrefObserver final {};

ForceInstallPrefObserver::ForceInstallPrefObserver(
    Profile* profile,
    const extensions::ExtensionId& extension_id)
    :{}

ForceInstallPrefObserver::~ForceInstallPrefObserver() = default;

void ForceInstallPrefObserver::Wait() {}

void ForceInstallPrefObserver::OnPrefChanged() {}

bool ForceInstallPrefObserver::IsForceInstallPrefSet() const {}

// Implements waiting for the mixin's specified event.
class ForceInstallWaiter final {};

ForceInstallWaiter::ForceInstallWaiter(
    ExtensionForceInstallMixin::WaitMode wait_mode,
    const extensions::ExtensionId& extension_id,
    Profile* profile)
    :{}

ForceInstallWaiter::~ForceInstallWaiter() = default;

bool ForceInstallWaiter::Wait() {}

void ForceInstallWaiter::WaitImpl(bool* success) {}

std::string GetServedUpdateManifestFileName(
    const extensions::ExtensionId& extension_id) {}

std::string GetServedCrxFileName(const extensions::ExtensionId& extension_id,
                                 const base::Version& extension_version) {}

std::string GenerateUpdateManifest(const extensions::ExtensionId& extension_id,
                                   const base::Version& extension_version,
                                   const GURL& crx_url) {}

bool ParseExtensionManifestData(const base::FilePath& extension_dir_path,
                                base::Version* extension_version) {}

bool ParseCrxOuterData(const base::FilePath& crx_path,
                       extensions::ExtensionId* extension_id) {}

bool ParseCrxInnerData(const base::FilePath& crx_path,
                       base::Version* extension_version) {}

std::string MakeForceInstallPolicyItemValue(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url) {}

void UpdatePolicyViaMockPolicyProvider(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url,
    policy::MockConfigurationPolicyProvider* mock_policy_provider) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)

void UpdatePolicyViaDeviceStateMixin(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url,
    ash::DeviceStateMixin* device_state_mixin) {
  device_state_mixin->RequestDevicePolicyUpdate()
      ->policy_payload()
      ->mutable_device_login_screen_extensions()
      ->add_device_login_screen_extensions(
          MakeForceInstallPolicyItemValue(extension_id, update_manifest_url));
}

void UpdatePolicyViaDevicePolicyCrosTestHelper(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url,
    policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper) {
  device_policy_cros_test_helper->device_policy()
      ->payload()
      .mutable_device_login_screen_extensions()
      ->add_device_login_screen_extensions(
          MakeForceInstallPolicyItemValue(extension_id, update_manifest_url));
  device_policy_cros_test_helper->RefreshDevicePolicy();
}

void UpdatePolicyViaEmbeddedPolicyMixin(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url,
    ash::EmbeddedPolicyTestServerMixin* policy_test_server_mixin,
    policy::UserPolicyBuilder* user_policy_builder,
    const std::string& account_id,
    const std::string& policy_type,
    bool* success) {
  user_policy_builder->payload()
      .mutable_extensioninstallforcelist()
      ->mutable_value()
      ->add_entries(
          MakeForceInstallPolicyItemValue(extension_id, update_manifest_url));
  user_policy_builder->Build();

  policy_test_server_mixin->UpdatePolicy(
      policy_type, account_id,
      user_policy_builder->payload().SerializeAsString());

  base::RunLoop run_loop;
  g_browser_process->policy_service()->RefreshPolicies(
      run_loop.QuitClosure(), policy::PolicyFetchReason::kTest);
  ASSERT_NO_FATAL_FAILURE(run_loop.Run());

  // Report the outcome via an output argument instead of the return value,
  // since ASSERT_NO_FATAL_FAILURE() only works in void functions.
  *success = true;
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

// Simulates a server error according to the current error mode, or returns no
// response when no error is configured. Note that this function is called on
// the IO thread.
std::unique_ptr<net::test_server::HttpResponse> ErrorSimulatingRequestHandler(
    std::atomic<ExtensionForceInstallMixin::ServerErrorMode>* server_error_mode,
    const net::test_server::HttpRequest& /*request*/) {}

}  // namespace

ExtensionForceInstallMixin::ExtensionForceInstallMixin(
    InProcessBrowserTestMixinHost* host)
    :{}

ExtensionForceInstallMixin::~ExtensionForceInstallMixin() = default;

void ExtensionForceInstallMixin::InitWithMockPolicyProvider(
    Profile* profile,
    policy::MockConfigurationPolicyProvider* mock_policy_provider) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)

void ExtensionForceInstallMixin::InitWithDeviceStateMixin(
    Profile* profile,
    ash::DeviceStateMixin* device_state_mixin) {
  DCHECK(device_state_mixin);
  DCHECK(!initialized_) << "Init already called";
  DCHECK(!profile_);
  DCHECK(!device_state_mixin_);
  initialized_ = true;
  profile_ = profile;
  device_state_mixin_ = device_state_mixin;
}

void ExtensionForceInstallMixin::InitWithDevicePolicyCrosTestHelper(
    Profile* profile,
    policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper) {
  DCHECK(device_policy_cros_test_helper);
  DCHECK(!initialized_) << "Init already called";
  DCHECK(!profile_);
  DCHECK(!device_policy_cros_test_helper_);
  initialized_ = true;
  profile_ = profile;
  device_policy_cros_test_helper_ = device_policy_cros_test_helper;
}

void ExtensionForceInstallMixin::InitWithEmbeddedPolicyMixin(
    Profile* profile,
    ash::EmbeddedPolicyTestServerMixin* policy_test_server_mixin,
    policy::UserPolicyBuilder* user_policy_builder,
    const std::string& account_id,
    const std::string& policy_type) {
  DCHECK(policy_test_server_mixin);
  DCHECK(user_policy_builder);
  DCHECK(!account_id.empty());
  DCHECK(!policy_type.empty());
  DCHECK(!initialized_) << "Init already called";
  DCHECK(!profile_);
  DCHECK(!policy_test_server_mixin_);
  DCHECK(!user_policy_builder_);
  DCHECK(account_id_.empty());
  DCHECK(policy_type_.empty());
  initialized_ = true;
  profile_ = profile;
  policy_test_server_mixin_ = policy_test_server_mixin;
  user_policy_builder_ = user_policy_builder;
  account_id_ = account_id;
  policy_type_ = policy_type;
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

bool ExtensionForceInstallMixin::ForceInstallFromCrx(
    const base::FilePath& crx_path,
    WaitMode wait_mode,
    extensions::ExtensionId* extension_id,
    base::Version* extension_version) {}

bool ExtensionForceInstallMixin::ForceInstallFromSourceDir(
    const base::FilePath& extension_dir_path,
    const std::optional<base::FilePath>& pem_path,
    WaitMode wait_mode,
    extensions::ExtensionId* extension_id,
    base::Version* extension_version) {}

bool ExtensionForceInstallMixin::UpdateFromCrx(
    const base::FilePath& crx_path,
    UpdateWaitMode wait_mode,
    base::Version* extension_version) {}

bool ExtensionForceInstallMixin::UpdateFromSourceDir(
    const base::FilePath& extension_dir_path,
    const extensions::ExtensionId& extension_id,
    UpdateWaitMode wait_mode,
    base::Version* extension_version) {}

const extensions::Extension* ExtensionForceInstallMixin::GetInstalledExtension(
    const extensions::ExtensionId& extension_id) const {}

const extensions::Extension* ExtensionForceInstallMixin::GetEnabledExtension(
    const extensions::ExtensionId& extension_id) const {}

void ExtensionForceInstallMixin::SetServerErrorMode(
    ServerErrorMode server_error_mode) {}

void ExtensionForceInstallMixin::SetUpOnMainThread() {}

base::FilePath ExtensionForceInstallMixin::GetPathInServedDir(
    const std::string& file_name) const {}

GURL ExtensionForceInstallMixin::GetServedUpdateManifestUrl(
    const extensions::ExtensionId& extension_id) const {}

GURL ExtensionForceInstallMixin::GetServedCrxUrl(
    const extensions::ExtensionId& extension_id,
    const base::Version& extension_version) const {}

bool ExtensionForceInstallMixin::ServeExistingCrx(
    const base::FilePath& source_crx_path,
    const extensions::ExtensionId& extension_id,
    const base::Version& extension_version) {}

bool ExtensionForceInstallMixin::CreateAndServeCrx(
    const base::FilePath& extension_dir_path,
    const std::optional<base::FilePath>& pem_path,
    const base::Version& extension_version,
    extensions::ExtensionId* extension_id) {}

bool ExtensionForceInstallMixin::ForceInstallFromServedCrx(
    const extensions::ExtensionId& extension_id,
    const base::Version& extension_version,
    WaitMode wait_mode) {}

bool ExtensionForceInstallMixin::CreateAndServeUpdateManifestFile(
    const extensions::ExtensionId& extension_id,
    const base::Version& extension_version) {}

bool ExtensionForceInstallMixin::UpdatePolicy(
    const extensions::ExtensionId& extension_id,
    const GURL& update_manifest_url) {}

bool ExtensionForceInstallMixin::WaitForExtensionUpdate(
    const extensions::ExtensionId& extension_id,
    const base::Version& extension_version,
    UpdateWaitMode wait_mode) {}