| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // 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/callback.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/time/tick_clock.h" |
| #include "base/time/time.h" |
| #include "components/feedback/anonymizer_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" |
| |
| 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(); |
| |
| // 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 std::string& 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 std::string& 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. |
| std::string 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 std::string& 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 std::string& 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. |
| content::BrowserContext* context_; |
| |
| // Provides a timer clock implementation for keeping track of access times. |
| // Can override the default clock for testing. |
| const base::TickClock* tick_clock_; |
| |
| // For removing PII from log strings from log sources. |
| scoped_refptr<base::SequencedTaskRunner> task_runner_for_anonymizer_; |
| scoped_refptr<feedback::AnonymizerToolContainer> anonymizer_container_; |
| |
| base::WeakPtrFactory<LogSourceAccessManager> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(LogSourceAccessManager); |
| }; |
| |
| } // namespace extensions |
| |
| #endif // EXTENSIONS_BROWSER_API_FEEDBACK_PRIVATE_LOG_SOURCE_ACCESS_MANAGER_H_ |