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
|
// 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 EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_LOG_SOURCE_ACCESS_MANAGER_H_
#define EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_LOG_SOURCE_ACCESS_MANAGER_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "components/feedback/redaction_tool/redaction_tool.h"
#include "components/feedback/system_logs/system_logs_source.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/api/feedback_private/access_rate_limiter.h"
#include "extensions/common/api/feedback_private.h"
#include "extensions/common/extension_id.h"
namespace extensions {
// Provides bookkeepping for SingleLogSource usage. It ensures that:
// - Each extension can have only one SingleLogSource for a particular source.
// - A source may not be accessed too frequently by an extension.
class LogSourceAccessManager {
public:
using ReadLogSourceCallback = base::OnceCallback<void(
std::unique_ptr<api::feedback_private::ReadLogSourceResult>)>;
explicit LogSourceAccessManager(content::BrowserContext* context);
LogSourceAccessManager(const LogSourceAccessManager&) = delete;
LogSourceAccessManager& operator=(const LogSourceAccessManager&) = delete;
~LogSourceAccessManager();
// Call this to override the maximum burst access count of the rate limiter.
static void SetMaxNumBurstAccessesForTesting(int num_accesses);
// To override the default rate-limiting mechanism of this function, pass in
// a TimeDelta representing the desired minimum time between consecutive reads
// of a source from an extension. Does not take ownership of `timeout`. When
// done testing, call this function again with `timeout`=nullptr to reset to
// the default behavior.
static void SetRateLimitingTimeoutForTesting(const base::TimeDelta* timeout);
// Override the default base::Time clock with a custom clock for testing.
void SetTickClockForTesting(const base::TickClock* clock) {
tick_clock_ = clock;
}
// Initiates a fetch from a log source, as specified in `params`. See
// feedback_private.idl for more info about the actual parameters.
bool FetchFromSource(const api::feedback_private::ReadLogSourceParams& params,
const ExtensionId& extension_id,
ReadLogSourceCallback callback);
// Each log source may not have more than this number of readers accessing it,
// regardless of extension.
static constexpr int kMaxReadersPerSource = 10;
private:
FRIEND_TEST_ALL_PREFIXES(LogSourceAccessManagerTest,
MaxNumberOfOpenLogSourcesSameExtension);
FRIEND_TEST_ALL_PREFIXES(LogSourceAccessManagerTest,
MaxNumberOfOpenLogSourcesDifferentExtensions);
// Contains a source/extension pair.
struct SourceAndExtension {
explicit SourceAndExtension(api::feedback_private::LogSource source,
const ExtensionId& extension_id);
bool operator<(const SourceAndExtension& other) const {
return std::make_pair(source, extension_id) <
std::make_pair(other.source, other.extension_id);
}
// The log source that this handle is accessing.
api::feedback_private::LogSource source;
// ID of the extension that opened this handle.
ExtensionId extension_id;
};
using ResourceId = int;
// Returned when there was an error creating a new resource or looking for an
// existing resource.
static constexpr ResourceId kInvalidResourceId = 0;
// Creates a new LogSourceResource for the source and extension indicated by
// `source` and `extension_id`. Stores the new resource in the API Resource
// Manager, and uses the resource ID as a key for a new entry in
// `open_handles_`, with value being a SourceAndExtension containing `source`
// and `extension_id`.
//
// Returns the nonzero ID of the newly created LogSourceResource, or
// `kInvalidResourceId` if a new resource could not be created.
ResourceId CreateResource(api::feedback_private::LogSource source,
const ExtensionId& extension_id);
// Callback that is passed to the log source from FetchFromSource.
// Arguments:
// - extension_id: ID of extension that opened the log source.
// - resource_id: Resource ID provided by API Resource Manager for the reader.
// - delete_source: Set this if the source opened by `handle` should be
// removed from both the API Resource Manager and from `open_handles_`.
// - callback: Callback for sending the response as a ReadLogSourceResult
// struct.
// - response: Contains the result from an operation to fetch from system
// log(s).
void OnFetchComplete(
const ExtensionId& extension_id,
ResourceId resource_id,
bool delete_source,
ReadLogSourceCallback callback,
std::unique_ptr<system_logs::SystemLogsResponse> response);
// Removes an existing log source handle indicated by `id` from
// `open_handles_`.
void RemoveHandle(ResourceId id);
// Returns the number of entries in `open_handles_` with source=`source`.
size_t GetNumActiveResourcesForSource(
api::feedback_private::LogSource source) const;
// Attempts to update the `last_access_time` field for the SourceAndExtension
// |open_handles_[id]|, to record that the source is being accessed by the
// handle right now. If less than `min_time_between_reads_` has elapsed since
// the last successful read, does not update `last_access_times`, and instead
// returns false. Otherwise returns true.
bool UpdateSourceAccessTime(ResourceId id);
// Keeps track of the last time each source was accessed by each extension.
// Each time FetchFromSource() is called, the timestamp gets updated.
//
// This intentionally kept separate from `sources_` because entries can be
// removed from and re-added to `sources_`, but that should not erase the
// recorded access times.
std::map<SourceAndExtension, std::unique_ptr<AccessRateLimiter>>
rate_limiters_;
// Contains all open handles, each uniquely identified by a ResourceId and
// additionally described by a SourceAndExtension struct.
std::map<ResourceId, std::unique_ptr<SourceAndExtension>> open_handles_;
// Keep count of the number of reader handles (resources) for each source.
std::map<api::feedback_private::LogSource, size_t> num_readers_per_source_;
// For fetching browser resources like ApiResourceManager.
raw_ptr<content::BrowserContext> context_;
// Provides a timer clock implementation for keeping track of access times.
// Can override the default clock for testing.
raw_ptr<const base::TickClock> tick_clock_;
// For removing PII from log strings from log sources.
scoped_refptr<base::SequencedTaskRunner> task_runner_for_redactor_;
scoped_refptr<redaction::RedactionToolContainer> redactor_container_;
base::WeakPtrFactory<LogSourceAccessManager> weak_factory_{this};
};
} // namespace extensions
#endif // EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_LOG_SOURCE_ACCESS_MANAGER_H_
|