summaryrefslogtreecommitdiff
path: root/chromium/extensions/browser/task_queue_util.cc
blob: 5ab77e6b38ed158b14f34cf8f76a7df7a3905931 (plain)
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
// 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