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
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_CORRUPTED_EXTENSION_REINSTALLER_H_
#define CHROME_BROWSER_EXTENSIONS_CORRUPTED_EXTENSION_REINSTALLER_H_
#include <map>
#include <optional>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/keyed_service/core/keyed_service.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/manifest.h"
#include "net/base/backoff_entry.h"
static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));
namespace content {
class BrowserContext;
}
namespace extensions {
// Class that asks ExtensionService to reinstall corrupted extensions.
// If a reinstallation fails for some reason (e.g. network unavailability) then
// it will retry reinstallation with backoff.
class CorruptedExtensionReinstaller : public KeyedService {
public:
// The reason why we want to reinstall the extension.
// Note: enum used for UMA. Do NOT reorder or remove entries. Don't forget to
// update enums.xml (name: ExtensionPolicyReinstallReason) when adding new
// entries.
enum class PolicyReinstallReason {
// Tried to load extension which was previously disabled because of
// corruption (but is a force-installed extension and therefore should be
// repaired).
// That happens when extension corruption was detected, but for some reason
// reinstall could not happen in the same session (no internet or session
// was closed right after detection), so at start of the next session we add
// extension to reinstall list again.
CORRUPTION_DETECTED_IN_PRIOR_SESSION = 0,
// Corruption detected in an extension from Chrome Web Store.
CORRUPTION_DETECTED_WEBSTORE = 1,
// Corruption detected in an extension outside Chrome Web Store.
CORRUPTION_DETECTED_NON_WEBSTORE = 2,
// Planned future option:
// Extension doesn't have hashes for corruption checks. This should not
// happen for extension from Chrome Web Store (since we can fetch hashes
// from server), but for extensions outside Chrome Web Store that means that
// we need to reinstall the extension (and compute hashes during
// installation).
// Not used currently, see https://crbug.com/958794#c22 for details.
// NO_UNSIGNED_HASHES_FOR_NON_WEBSTORE = 3,
// Extension doesn't have hashes for corruption checks. Ideally this
// extension should be reinstalled in this case, but currently we just skip
// them. See https://crbug.com/958794#c22 for details.
NO_UNSIGNED_HASHES_FOR_NON_WEBSTORE_SKIP = 4,
// Magic constant used by the histogram macros.
// Always update it to the max value.
kMaxValue = NO_UNSIGNED_HASHES_FOR_NON_WEBSTORE_SKIP
};
using ReinstallCallback =
base::RepeatingCallback<void(base::OnceClosure callback,
base::TimeDelta delay)>;
static CorruptedExtensionReinstaller* Get(content::BrowserContext* context);
CorruptedExtensionReinstaller(const CorruptedExtensionReinstaller&) = delete;
CorruptedExtensionReinstaller& operator=(
const CorruptedExtensionReinstaller&) = delete;
~CorruptedExtensionReinstaller() override;
// Records UMA metrics about policy reinstall to UMA. Temporarily exposed
// publicly because we now skip reinstall for non-webstore policy
// force-installed extensions without hashes, but are interested in number
// of such cases.
// See https://crbug.com/958794#c22 for details.
void RecordPolicyReinstallReason(PolicyReinstallReason reason_for_uma);
// Notifies the manager that we are reinstalling the policy force-installed
// extension with `id` because we detected corruption in the current copy.
// `reason_for_uma` indicates origin and details of the requires, and is used
// for statistics purposes (sent to UMA). `manifest_location_for_uma` is the
// manifest location, and is used for statistics purposes (sent to UMA)
void ExpectReinstallForCorruption(
const ExtensionId& id,
std::optional<PolicyReinstallReason> reason_for_uma,
mojom::ManifestLocation manifest_location_for_uma);
// Call this method when extension in reinstalled to remove it from the set
// and update the metrics.
void MarkResolved(const ExtensionId& id);
// Returns true if we are expecting a reinstall of the extension with `id` due
// to corruption?
bool IsReinstallForCorruptionExpected(const ExtensionId& id) const;
// Whether or not there are any corrupted extensions.
bool HasAnyReinstallForCorruption() const;
// Gets the view on extensions scheduled for reinstall.
const std::map<ExtensionId, base::TimeTicks>& GetExpectedReinstalls() const;
// Notifies this reinstaller about an extension corruption.
void NotifyExtensionDisabledDueToCorruption();
// KeyedService:
void Shutdown() override;
// For tests, overrides the default action to take to initiate reinstalls.
static void set_reinstall_action_for_test(ReinstallCallback* action);
private:
friend class CorruptedExtensionReinstallerFactory;
explicit CorruptedExtensionReinstaller(content::BrowserContext* context);
void Fire();
base::TimeDelta GetNextFireDelay();
void ScheduleNextReinstallAttempt();
const raw_ptr<content::BrowserContext, DanglingUntriaged> context_ = nullptr;
// A set of extension ids that are being reinstalled due to corruption, mapped
// to the time we detected the corruption.
std::map<ExtensionId, base::TimeTicks> expected_reinstalls_;
net::BackoffEntry backoff_entry_;
// Whether or not there is a pending PostTask to Fire().
bool scheduled_fire_pending_ = false;
base::WeakPtrFactory<CorruptedExtensionReinstaller> weak_factory_{this};
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_CORRUPTED_EXTENSION_REINSTALLER_H_
|