blob: 5967afac30fd30302deebe07e4b15907e9ee89db [file] [log] [blame]
// Copyright 2017 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.
#include "extensions/browser/extension_registrar.h"
#include "base/logging.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/renderer_startup_helper.h"
namespace extensions {
ExtensionRegistrar::ExtensionRegistrar(content::BrowserContext* browser_context)
: extension_system_(ExtensionSystem::Get(browser_context)),
registry_(ExtensionRegistry::Get(browser_context)),
renderer_helper_(
RendererStartupHelperFactory::GetForBrowserContext(browser_context)),
weak_factory_(this) {}
ExtensionRegistrar::~ExtensionRegistrar() = default;
void ExtensionRegistrar::EnableExtension(
scoped_refptr<const Extension> extension) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
registry_->RemoveDisabled(extension->id());
registry_->AddEnabled(extension);
// The URLRequestContexts need to be first to know that the extension
// was loaded. Otherwise a race can arise where a renderer that is created
// for the extension may try to load an extension URL with an extension id
// that the request context doesn't yet know about. The BrowserContext should
// ensure its URLRequestContexts appropriately discover the loaded extension.
extension_system_->RegisterExtensionWithRequestContexts(
extension.get(),
base::Bind(&ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts,
weak_factory_.GetWeakPtr(), extension));
renderer_helper_->OnExtensionLoaded(*extension);
// Tell subsystems that use the ExtensionRegistryObserver::OnExtensionLoaded
// about the new extension.
//
// NOTE: It is important that this happen after notifying the renderers about
// the new extensions so that if we navigate to an extension URL in
// ExtensionRegistryObserver::OnExtensionLoaded the renderer is guaranteed to
// know about it.
registry_->TriggerOnLoaded(extension.get());
}
void ExtensionRegistrar::DisableExtension(
scoped_refptr<const Extension> extension) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Move the extension to the disabled list.
registry_->RemoveEnabled(extension->id());
registry_->AddDisabled(extension);
DeactivateExtension(extension.get(), UnloadedExtensionReason::DISABLE);
NotifyExtensionDisabledOrRemoved(extension->id(),
UnloadedExtensionReason::DISABLE);
}
void ExtensionRegistrar::RemoveExtension(const ExtensionId& extension_id,
UnloadedExtensionReason reason) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
int include_mask =
ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::TERMINATED;
scoped_refptr<const Extension> extension(
registry_->GetExtensionById(extension_id, include_mask));
if (registry_->disabled_extensions().Contains(extension_id)) {
registry_->RemoveDisabled(extension_id);
// The extension is already deactivated.
} else if (extension) {
registry_->RemoveEnabled(extension_id);
DeactivateExtension(extension.get(), reason);
}
NotifyExtensionDisabledOrRemoved(extension_id, reason);
}
void ExtensionRegistrar::DeactivateExtension(const Extension* extension,
UnloadedExtensionReason reason) {
registry_->TriggerOnUnloaded(extension, reason);
renderer_helper_->OnExtensionUnloaded(*extension);
}
void ExtensionRegistrar::NotifyExtensionDisabledOrRemoved(
const ExtensionId& extension_id,
UnloadedExtensionReason reason) {
extension_system_->UnregisterExtensionWithRequestContexts(extension_id,
reason);
}
void ExtensionRegistrar::OnExtensionRegisteredWithRequestContexts(
scoped_refptr<const Extension> extension) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
registry_->AddReady(extension);
if (registry_->enabled_extensions().Contains(extension->id()))
registry_->TriggerOnReady(extension.get());
}
} // namespace extensions