blob: 5ab77e6b38ed158b14f34cf8f76a7df7a3905931 [file] [log] [blame]
// Copyright 2019 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/task_queue_util.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/lazy_background_task_queue.h"
#include "extensions/browser/lazy_context_id.h"
#include "extensions/browser/service_worker_task_queue.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
namespace extensions {
namespace {
// Get the ServiceWorkerTaskQueue instance for the BrowserContext.
//
ServiceWorkerTaskQueue* GetServiceWorkerTaskQueueForBrowserContext(
content::BrowserContext* browser_context,
bool is_split_mode) {
content::BrowserContext* context_to_use = browser_context;
// Incognito extensions in split mode use their own task queue, while those
// in spanning mode use the task queue of the original BrowserContext.
if (browser_context->IsOffTheRecord() && !is_split_mode) {
context_to_use =
ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context);
}
return ServiceWorkerTaskQueue::Get(context_to_use);
}
// Get the ServiceWorkerTaskQueue instance for the extension.
//
// Only call this for a SW-based extension.
ServiceWorkerTaskQueue* GetServiceWorkerTaskQueueForExtension(
content::BrowserContext* browser_context,
const Extension* extension) {
DCHECK(BackgroundInfo::IsServiceWorkerBased(extension));
return GetServiceWorkerTaskQueueForBrowserContext(
browser_context, IncognitoInfo::IsSplitMode(extension));
}
// Get the ServiceWorkerTaskQueue instance for the extension ID.
//
// Only call this for a SW-based extension.
ServiceWorkerTaskQueue* GetServiceWorkerTaskQueueForExtensionId(
content::BrowserContext* browser_context,
const ExtensionId& extension_id) {
// Incognito extensions in split mode use their own task queue, while those
// in spanning mode use the task queue of the original BrowserContext.
// This is an optimization to avoid looking up an Extension instance,
// since we only need it for the off-the-record case.
if (!browser_context->IsOffTheRecord()) {
return ServiceWorkerTaskQueue::Get(browser_context);
}
const Extension* extension = ExtensionRegistry::Get(browser_context)
->enabled_extensions()
.GetByID(extension_id);
DCHECK(extension);
return GetServiceWorkerTaskQueueForExtension(browser_context, extension);
}
// Use a pointer-to-member function so we can use the same logic for the
// activation and deactivation paths.
using TaskQueueFunction = void (ServiceWorkerTaskQueue::*)(const Extension*);
void DoTaskQueueFunction(content::BrowserContext* browser_context,
const Extension* extension,
TaskQueueFunction function) {
// This is only necessary for service worker-based extensions.
if (!BackgroundInfo::IsServiceWorkerBased(extension))
return;
ServiceWorkerTaskQueue* const queue =
ServiceWorkerTaskQueue::Get(browser_context);
(queue->*function)(extension);
// There is a separate task queue for the off-the-record context
// for any extension running in split mode.
if (!ExtensionsBrowserClient::Get()->HasOffTheRecordContext(
browser_context) ||
!IncognitoInfo::IsSplitMode(extension) ||
!ExtensionsBrowserClient::Get()->IsExtensionIncognitoEnabled(
extension->id(), browser_context)) {
return;
}
content::BrowserContext* off_the_record_context =
ExtensionsBrowserClient::Get()->GetOffTheRecordContext(browser_context);
DCHECK(off_the_record_context);
ServiceWorkerTaskQueue* const off_the_record_queue =
ServiceWorkerTaskQueue::Get(off_the_record_context);
(off_the_record_queue->*function)(extension);
}
} // anonymous namespace
LazyContextTaskQueue* GetTaskQueueForLazyContextId(
const LazyContextId& context_id) {
if (context_id.is_for_event_page())
return LazyBackgroundTaskQueue::Get(context_id.browser_context());
DCHECK(context_id.is_for_service_worker());
return GetServiceWorkerTaskQueueForExtensionId(context_id.browser_context(),
context_id.extension_id());
}
void ActivateTaskQueueForExtension(content::BrowserContext* browser_context,
const Extension* extension) {
DCHECK(!browser_context->IsOffTheRecord());
DoTaskQueueFunction(browser_context, extension,
&ServiceWorkerTaskQueue::ActivateExtension);
}
void DeactivateTaskQueueForExtension(content::BrowserContext* browser_context,
const Extension* extension) {
DCHECK(!browser_context->IsOffTheRecord());
DoTaskQueueFunction(browser_context, extension,
&ServiceWorkerTaskQueue::DeactivateExtension);
}
} // namespace extensions