1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// Copyright 2019 The Chromium Authors
// 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/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 {
#if DCHECK_IS_ON()
// Whether the task queue is allowed to be created for OTR profile.
bool IsOffTheRecordContextAllowed(content::BrowserContext* browser_context) {
#if BUILDFLAG(IS_CHROMEOS)
// In Guest mode on Chrome OS we want to create a task queue for OTR profile.
if (ExtensionsBrowserClient::Get()->IsGuestSession(browser_context)) {
return true;
}
#endif
// In other cases don't create a task queue for OTR profile.
return false;
}
#endif // DCHECK_IS_ON()
// 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) {
#if DCHECK_IS_ON()
DCHECK(IsOffTheRecordContextAllowed(browser_context) ||
!browser_context->IsOffTheRecord());
#endif // DCHECK_IS_ON()
// 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.IsForBackgroundPage()) {
return LazyBackgroundTaskQueue::Get(context_id.browser_context());
}
if (context_id.IsForServiceWorker()) {
return GetServiceWorkerTaskQueueForExtensionId(context_id.browser_context(),
context_id.extension_id());
}
return nullptr;
}
void ActivateTaskQueueForExtension(content::BrowserContext* browser_context,
const Extension* extension) {
DoTaskQueueFunction(browser_context, extension,
&ServiceWorkerTaskQueue::ActivateExtension);
}
void DeactivateTaskQueueForExtension(content::BrowserContext* browser_context,
const Extension* extension) {
DoTaskQueueFunction(browser_context, extension,
&ServiceWorkerTaskQueue::DeactivateExtension);
}
} // namespace extensions
|