File: delayed_install_manager.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (159 lines) | stat: -rw-r--r-- 5,136 bytes parent folder | download | duplicates (5)
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
152
153
154
155
156
157
158
159
// Copyright 2025 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/delayed_install_manager.h"

#include <string>
#include <vector>

#include "base/check.h"
#include "base/trace_event/trace_event.h"
#include "extensions/browser/delayed_install_manager_factory.h"
#include "extensions/browser/extension_registrar.h"
#include "extensions/browser/install_gate.h"

namespace extensions {

DelayedInstallManager::DelayedInstallManager(content::BrowserContext* context)
    : extension_prefs_(ExtensionPrefs::Get(context)),
      extension_registrar_(ExtensionRegistrar::Get(context)) {}

DelayedInstallManager::~DelayedInstallManager() = default;

// static
DelayedInstallManager* DelayedInstallManager::Get(
    content::BrowserContext* context) {
  return DelayedInstallManagerFactory::GetForBrowserContext(context);
}

void DelayedInstallManager::Shutdown() {
  // Avoids dangling pointers during keyed service two-phase shutdown.
  extension_prefs_ = nullptr;
  extension_registrar_ = nullptr;
}

bool DelayedInstallManager::Contains(const ExtensionId& id) const {
  return delayed_installs_.Contains(id);
}

void DelayedInstallManager::Insert(scoped_refptr<const Extension> extension) {
  delayed_installs_.Insert(extension);
}

void DelayedInstallManager::Remove(const ExtensionId& id) {
  delayed_installs_.Remove(id);
}

const Extension* DelayedInstallManager::GetPendingExtensionUpdate(
    const ExtensionId& id) const {
  return delayed_installs_.GetByID(id);
}

void DelayedInstallManager::FinishInstallationsDelayedByShutdown() {
  TRACE_EVENT0("browser,startup",
               "DelayedInstallManager::FinishInstallationsDelayedByShutdown");

  const ExtensionPrefs::ExtensionsInfo delayed_info =
      extension_prefs_->GetAllDelayedInstallInfo();
  for (const auto& info : delayed_info) {
    scoped_refptr<const Extension> extension;
    if (info.extension_manifest) {
      std::string error;
      extension = Extension::Create(
          info.extension_path, info.extension_location,
          *info.extension_manifest,
          extension_prefs_->GetDelayedInstallCreationFlags(info.extension_id),
          info.extension_id, &error);
      if (extension.get()) {
        delayed_installs_.Insert(extension);
      }
    }
  }
  MaybeFinishDelayedInstallations();
}

void DelayedInstallManager::MaybeFinishDelayedInstallations() {
  std::vector<std::string> to_be_installed;
  for (const auto& extension : delayed_installs_) {
    to_be_installed.push_back(extension->id());
  }
  for (const auto& extension_id : to_be_installed) {
    FinishDelayedInstallationIfReady(extension_id,
                                     /*install_immediately=*/false);
  }
}

bool DelayedInstallManager::FinishDelayedInstallationIfReady(
    const std::string& extension_id,
    bool install_immediately) {
  // Check if the extension already got installed.
  const Extension* extension = delayed_installs_.GetByID(extension_id);
  if (!extension) {
    return false;
  }

  ExtensionPrefs::DelayReason reason;
  const InstallGate::Action action =
      ShouldDelayExtensionInstall(extension, install_immediately, &reason);
  switch (action) {
    case InstallGate::INSTALL:
      break;
    case InstallGate::DELAY:
      // Bail out and continue to delay the install.
      return false;
    case InstallGate::ABORT:
      delayed_installs_.Remove(extension_id);
      // Make sure no version of the extension is actually installed, (i.e.,
      // that this delayed install was not an update).
      CHECK(!extension_prefs_->GetInstalledExtensionInfo(extension_id));
      extension_prefs_->DeleteExtensionPrefs(extension_id);
      return false;
  }

  scoped_refptr<const Extension> delayed_install =
      GetPendingExtensionUpdate(extension_id);
  CHECK(delayed_install.get());
  delayed_installs_.Remove(extension_id);

  if (!extension_prefs_->FinishDelayedInstallInfo(extension_id)) {
    NOTREACHED();
  }

  extension_registrar_->FinishInstallation(delayed_install.get());
  return true;
}

void DelayedInstallManager::RegisterInstallGate(
    ExtensionPrefs::DelayReason reason,
    InstallGate* install_delayer) {
  DCHECK(install_delayer_registry_.end() ==
         install_delayer_registry_.find(reason));
  install_delayer_registry_[reason] = install_delayer;
}

void DelayedInstallManager::UnregisterInstallGate(
    InstallGate* install_delayer) {
  std::erase_if(install_delayer_registry_, [&](const auto& pair) {
    return pair.second == install_delayer;
  });
}

InstallGate::Action DelayedInstallManager::ShouldDelayExtensionInstall(
    const Extension* extension,
    bool install_immediately,
    ExtensionPrefs::DelayReason* reason) const {
  for (const auto& entry : install_delayer_registry_) {
    InstallGate* const delayer = entry.second;
    InstallGate::Action action =
        delayer->ShouldDelay(extension, install_immediately);
    if (action != InstallGate::INSTALL) {
      *reason = entry.first;
      return action;
    }
  }

  return InstallGate::INSTALL;
}

}  // namespace extensions