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
|
// 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_INSPECTOR_H_
#define CHROME_BROWSER_WIN_CONFLICTS_MODULE_INSPECTOR_H_
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/task_traits.h"
#include "base/timer/timer.h"
#include "chrome/browser/win/conflicts/inspection_results_cache.h"
#include "chrome/browser/win/conflicts/module_database_observer.h"
#include "chrome/browser/win/conflicts/module_info.h"
#include "chrome/services/util_win/public/mojom/util_win.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace base {
class SequencedTaskRunner;
}
// This class takes care of inspecting several modules (identified by their
// ModuleInfoKey) and returning the result via the OnModuleInspectedCallback on
// the SequencedTaskRunner where it was created.
//
// The inspection of all modules is quite expensive in terms of resources, so it
// is done one by one, in a utility process, only if it is needed (when
// StartInspection() is called).
//
// This class is not thread safe and it enforces safety via a SEQUENCE_CHECKER.
class ModuleInspector : public ModuleDatabaseObserver {
public:
// The amount of time before the |inspection_results_cache_| is flushed to
// disk while the ModuleDatabase is not idle.
static constexpr base::TimeDelta kFlushInspectionResultsTimerTimeout =
base::Minutes(5);
using OnModuleInspectedCallback =
base::RepeatingCallback<void(const ModuleInfoKey& module_key,
ModuleInspectionResult inspection_result)>;
explicit ModuleInspector(
const OnModuleInspectedCallback& on_module_inspected_callback);
ModuleInspector(const ModuleInspector&) = delete;
ModuleInspector& operator=(const ModuleInspector&) = delete;
~ModuleInspector() override;
// Starts the background inspection of modules.
void StartInspection();
// Adds the module to the queue of modules to inspect. Starts the inspection
// process if the |queue_| is empty.
void AddModule(const ModuleInfoKey& module_key);
// Returns true if ModuleInspector is not doing anything right now.
bool IsIdle();
// ModuleDatabaseObserver:
void OnModuleDatabaseIdle() override;
static base::FilePath GetInspectionResultsCachePath();
// Sets a test factory function to create the UtilWin instance.
using UtilWinFactoryCallback =
base::RepeatingCallback<mojo::Remote<chrome::mojom::UtilWin>()>;
void SetUtilWinFactoryCallbackForTesting(
UtilWinFactoryCallback util_win_factory_callback);
int get_connection_error_retry_count_for_testing() const {
return connection_error_retry_count_;
}
private:
// Ensures the |remote_util_win_| instance is bound to the UtilWin service.
void EnsureUtilWinServiceBound();
// Invoked when the InspectionResultsCache is available.
void OnInspectionResultsCacheRead(
InspectionResultsCache inspection_results_cache);
// Handles a connection error to the UtilWin service.
void OnUtilWinServiceConnectionError();
// Starts inspecting the module at the front of the queue.
void StartInspectingModule();
// Adds the newly inspected module to the cache then calls
// OnInspectionFinished().
void OnModuleNewlyInspected(const ModuleInfoKey& module_key,
ModuleInspectionResult inspection_result);
// Called back on the execution context on which the ModuleInspector was
// created when a module has finished being inspected. The callback will be
// executed and, if the |queue_| is not empty, the next module will be sent
// for inspection.
void OnInspectionFinished(const ModuleInfoKey& module_key,
ModuleInspectionResult inspection_result);
// Sends a task on a blocking background sequence to serialize
// |inspection_results_cache_|, should it be needed.
void MaybeUpdateInspectionResultsCache();
OnModuleInspectedCallback on_module_inspected_callback_;
// The modules are put in queue until they are sent for inspection.
base::queue<ModuleInfoKey> queue_;
// Indicates inspection was started. Used to delay the background inspection
// tasks until the results have been requested (by calling StartInspection()).
bool is_started_;
// A callback used to initialize |remote_util_win_|.
UtilWinFactoryCallback util_win_factory_callback_;
// A remote interface to the UtilWin service. It is created when inspection is
// ongoing, and freed when no longer needed.
mojo::Remote<chrome::mojom::UtilWin> remote_util_win_;
// The vector of paths to %env_var%, used to account for differences in
// localization and where people keep their files.
// e.g. c:\windows vs d:\windows
StringMapping path_mapping_;
// This task runner handles updates to the inspection results cache.
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
// Indicates if the inspection results cache was read from disk.
bool inspection_results_cache_read_;
// Contains the cached inspection results so that a module is not inspected
// more than once between restarts.
InspectionResultsCache inspection_results_cache_;
// Ensures that newly inspected modules are flushed to the disk after at most
// 5 minutes to avoid losing too much of the work done if the browser is
// closed before all modules are inspected.
base::RetainingOneShotTimer flush_inspection_results_timer_;
// Indicates if a module was newly inspected and the cache must be updated.
bool has_new_inspection_results_;
// The number of time this class will try to restart the UtilWin service if a
// connection error occurs. This is to prevent the degenerate case where the
// service always fails to start and the restart cycle happens infinitely.
int connection_error_retry_count_;
// Indicates if a module is currently being inspected asynchronously by the
// UtilWin service.
bool is_waiting_on_util_win_service_;
SEQUENCE_CHECKER(sequence_checker_);
// Weak pointers are used to safely post the inspection result back to the
// ModuleInspector from the task scheduler.
base::WeakPtrFactory<ModuleInspector> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_WIN_CONFLICTS_MODULE_INSPECTOR_H_
|