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 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
// 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_WIN_CONFLICTS_MODULE_DATABASE_H_
#define CHROME_BROWSER_WIN_CONFLICTS_MODULE_DATABASE_H_
#include <map>
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/win/conflicts/module_info.h"
#include "chrome/browser/win/conflicts/module_inspector.h"
#include "chrome/browser/win/conflicts/third_party_metrics_recorder.h"
#include "content/public/common/process_type.h"
class ModuleDatabaseObserver;
namespace base {
class FilePath;
class SequencedTaskRunner;
} // namespace base
// A class that keeps track of all modules loaded across Chrome processes.
//
// It is also the main class behind third-party modules tracking, and owns the
// different classes that required to identify incompatible applications and
// record metrics.
//
// This is effectively a singleton, but doesn't use base::Singleton. The intent
// is for the object to be created when Chrome is single-threaded, and for it
// be set as the process-wide singleton via SetInstance.
class ModuleDatabase : public ModuleDatabaseEventSource {
public:
// Structures for maintaining information about modules.
using ModuleMap = std::map<ModuleInfoKey, ModuleInfoData>;
using ModuleInfo = ModuleMap::value_type;
// The Module Database becomes idle after this timeout expires without any
// module events.
static constexpr base::TimeDelta kIdleTimeout = base::Seconds(10);
// Creates the ModuleDatabase. Must be created and set on the sequence
// returned by GetTaskRunner().
ModuleDatabase();
ModuleDatabase(const ModuleDatabase&) = delete;
ModuleDatabase& operator=(const ModuleDatabase&) = delete;
~ModuleDatabase() override;
// Returns the SequencedTaskRunner on which the ModuleDatabase lives. Can be
// called on any thread.
static scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();
// Retrieves the singleton global instance of the ModuleDatabase. Must only be
// called on the sequence returned by GetTaskRunner().
static ModuleDatabase* GetInstance();
// Sets the global instance of the ModuleDatabase. Ownership is passed to the
// global instance and deliberately leaked, unless manually cleaned up. This
// has no locking and should be called when Chrome is single threaded.
static void SetInstance(std::unique_ptr<ModuleDatabase> module_database);
// Returns true if the ModuleDatabase is idle. This means that no modules are
// currently being inspected, and no new module events have been observed in
// the last 10 seconds.
bool IsIdle();
// Indicates that a new registered shell extension was found.
void OnShellExtensionEnumerated(const base::FilePath& path,
uint32_t size_of_image,
uint32_t time_date_stamp);
// Indicates that all shell extensions have been enumerated.
void OnShellExtensionEnumerationFinished();
// Indicates that a new registered input method editor was found.
void OnImeEnumerated(const base::FilePath& path,
uint32_t size_of_image,
uint32_t time_date_stamp);
// Indicates that all input method editors have been enumerated.
void OnImeEnumerationFinished();
// Indicates that a module has been loaded. The data passed to this function
// is taken as gospel, so if it originates from a remote process it should be
// independently validated first. (In practice, see ModuleEventSinkImpl for
// details of where this happens.)
void OnModuleLoad(content::ProcessType process_type,
const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp);
// Forwards the module load event to the ModuleDatabase global instance via
// OnModuleLoad() on the ModuleDatabase task runner. Can be called on any
// threads. Provided for convenience.
static void HandleModuleLoadEvent(content::ProcessType process_type,
const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp);
void OnModuleBlocked(const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp);
// Marks the module as added to the module blocklist cache, which means it
// will be blocked on the next browser launch.
void OnModuleAddedToBlocklist(const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp);
// TODO(chrisha): Module analysis code, and various accessors for use by
// chrome://conflicts.
// Adds or removes an observer.
// Note that when adding an observer, OnNewModuleFound() will immediately be
// called once for all modules that are already loaded before returning to the
// caller. In addition, if the ModuleDatabase is currently idle,
// OnModuleDatabaseIdle() will also be invoked.
//
// ModuleDatabaseEventSource:
void AddObserver(ModuleDatabaseObserver* observer) override;
void RemoveObserver(ModuleDatabaseObserver* observer) override;
void StartInspection();
private:
friend class TestModuleDatabase;
friend class ModuleDatabaseTest;
friend class ModuleEventSinkImplTest;
ModuleInfo* CreateModuleInfo(const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp);
// Finds or creates a mutable ModuleInfo entry. Returns true if the module
// info was created.
bool FindOrCreateModuleInfo(const base::FilePath& module_path,
uint32_t module_size,
uint32_t module_time_date_stamp,
ModuleInfo** module_info);
// Returns true if the enumeration of the IMEs and the shell extensions is
// finished.
//
// To avoid sending an improperly tagged module to an observer (in case a race
// condition happens and the module is loaded before the enumeration is done),
// it's important that this function returns true before any calls to
// OnNewModuleFound() is made.
bool RegisteredModulesEnumerated();
// Called when RegisteredModulesEnumerated() becomes true. Notifies the
// observers of each already inspected modules and checks if the idle state
// should be entered.
void OnRegisteredModulesEnumerated();
// Callback for ModuleInspector.
void OnModuleInspected(const ModuleInfoKey& module_key,
ModuleInspectionResult inspection_result);
// If the ModuleDatabase is truly idle, calls EnterIdleState().
void OnDelayExpired();
// Notifies the observers that ModuleDatabase is now idle.
void EnterIdleState();
// Notifies the |observer| of already found and inspected modules via
// OnNewModuleFound().
void NotifyLoadedModules(ModuleDatabaseObserver* observer);
// A map of all known modules.
ModuleMap modules_;
base::RetainingOneShotTimer idle_timer_;
// Indicates if the ModuleDatabase has started processing module load events.
bool has_started_processing_;
// Indicates if all shell extensions have been enumerated.
bool shell_extensions_enumerated_;
// Indicates if all input method editors have been enumerated.
bool ime_enumerated_;
// Inspects new modules on a blocking task runner.
ModuleInspector module_inspector_;
// Holds observers.
base::ObserverList<ModuleDatabaseObserver>::Unchecked observer_list_;
// Records metrics on third-party modules.
ThirdPartyMetricsRecorder third_party_metrics_;
SEQUENCE_CHECKER(sequence_checker_);
};
#endif // CHROME_BROWSER_WIN_CONFLICTS_MODULE_DATABASE_H_
|