// Copyright 2016 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/ash/accessibility/accessibility_extension_loader.h"
#include <utility>
#include "base/functional/callback.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "components/user_manager/user.h"
#include "extensions/browser/extension_system.h"
namespace ash {
AccessibilityExtensionLoader::AccessibilityExtensionLoader(
const std::string& extension_id,
const base::FilePath& extension_path,
const base::FilePath::CharType* manifest_filename,
const base::FilePath::CharType* guest_manifest_filename,
base::RepeatingClosure unload_callback)
: extension_id_(extension_id),
extension_path_(extension_path),
manifest_filename_(manifest_filename),
guest_manifest_filename_(guest_manifest_filename),
unload_callback_(unload_callback) {}
AccessibilityExtensionLoader::~AccessibilityExtensionLoader() = default;
void AccessibilityExtensionLoader::SetBrowserContext(
content::BrowserContext* browser_context,
base::OnceClosure done_callback) {
content::BrowserContext* prev_browser_context = browser_context_;
browser_context_ = browser_context;
if (!loaded_)
return;
// If the extension was loaded on the previous browser context (which isn't
// the current browser context), unload it there.
if (prev_browser_context && prev_browser_context != browser_context) {
UnloadExtension(prev_browser_context);
}
// If the extension was already enabled, but not for this profile, add it
// to this profile.
auto* extension_service =
extensions::ExtensionSystem::Get(browser_context_)->extension_service();
auto* component_loader = extension_service->component_loader();
if (!component_loader->Exists(extension_id_)) {
LoadExtension(browser_context_, std::move(done_callback));
}
}
void AccessibilityExtensionLoader::Load(
content::BrowserContext* browser_context,
base::OnceClosure done_cb) {
browser_context_ = browser_context;
if (loaded_)
return;
loaded_ = true;
LoadExtension(browser_context_, std::move(done_cb));
}
void AccessibilityExtensionLoader::Unload() {
if (loaded_) {
UnloadExtension(browser_context_);
UnloadExtension(BrowserContextHelper::Get()->GetSigninBrowserContext());
loaded_ = false;
}
browser_context_ = nullptr;
if (unload_callback_) {
unload_callback_.Run();
}
}
//
// private
//
void AccessibilityExtensionLoader::LoadExtension(
content::BrowserContext* browser_context,
base::OnceClosure done_cb) {
DCHECK(manifest_filename_);
DCHECK(guest_manifest_filename_);
extensions::ExtensionService* extension_service =
extensions::ExtensionSystem::Get(browser_context)->extension_service();
// In Kiosk mode, we should reinstall the extension upon first load. This way,
// no state from the previous session is preserved.
const user_manager::User* user =
BrowserContextHelper::Get()->GetUserByBrowserContext(browser_context);
if (user && user->IsKioskType() && !was_reset_for_kiosk_) {
was_reset_for_kiosk_ = true;
extension_service->DisableExtension(
extension_id_, extensions::disable_reason::DISABLE_REINSTALL);
done_cb = base::BindOnce(
&AccessibilityExtensionLoader::ReinstallExtensionForKiosk,
weak_ptr_factory_.GetWeakPtr(), browser_context, std::move(done_cb));
}
extension_service->component_loader()
->AddComponentFromDirWithManifestFilename(
extension_path_, extension_id_.c_str(), manifest_filename_,
guest_manifest_filename_, std::move(done_cb));
}
void AccessibilityExtensionLoader::ReinstallExtensionForKiosk(
content::BrowserContext* browser_context,
base::OnceClosure done_cb) {
DCHECK(was_reset_for_kiosk_);
auto* extension_service =
extensions::ExtensionSystem::Get(browser_context)->extension_service();
std::u16string error;
extension_service->UninstallExtension(
extension_id_, extensions::UninstallReason::UNINSTALL_REASON_REINSTALL,
&error);
extension_service->component_loader()->Reload(extension_id_);
if (done_cb)
std::move(done_cb).Run();
}
void AccessibilityExtensionLoader::UnloadExtension(
content::BrowserContext* browser_context) {
auto* extension_service =
extensions::ExtensionSystem::Get(browser_context)->extension_service();
extension_service->component_loader()->Remove(extension_id_);
}
} // namespace ash