Chromium Code Reviews| Index: chrome/browser/extensions/api/feedback_private/log_source_access_manager.cc |
| diff --git a/chrome/browser/extensions/api/feedback_private/log_source_access_manager.cc b/chrome/browser/extensions/api/feedback_private/log_source_access_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..92f6bde790ca1784c559bdb03edbed4c79c211d1 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/api/feedback_private/log_source_access_manager.cc |
| @@ -0,0 +1,110 @@ |
| +// 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. |
| + |
| +#include "chrome/browser/extensions/api/feedback_private/log_source_access_manager.h" |
| + |
| +#include <algorithm> |
| +#include <utility> |
| + |
| +#include "base/bind.h" |
| +#include "base/time/default_tick_clock.h" |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
| +#if defined(OS_CHROMEOS) |
| +// The minimum time between consecutive reads of a log source by a particular |
| +// extension. |
| +const int kDefaultRateLimitingTimeoutMs = 1000; |
| + |
| +// If this is null, then |kDefaultRateLimitingTimeoutMs| is used as the timeout. |
| +const base::TimeDelta* g_rate_limiting_timeout = nullptr; |
| +#endif // defined(OS_CHROMEOS) |
| + |
| +base::TimeDelta GetMinTimeBetweenReads() { |
| + return g_rate_limiting_timeout |
| + ? *g_rate_limiting_timeout |
| + : base::TimeDelta::FromMilliseconds(kDefaultRateLimitingTimeoutMs); |
| +} |
| + |
| +} // namespace |
| + |
| +LogSourceAccessManager::SourceAndExtension::SourceAndExtension( |
| + api::feedback_private::LogSource source, |
| + const std::string& extension_id) |
| + : source(source), extension_id(extension_id) {} |
| + |
| +LogSourceAccessManager::LogSourceAccessManager() |
| + : tick_clock_(new base::DefaultTickClock), weak_factory_(this) {} |
| + |
| +LogSourceAccessManager::~LogSourceAccessManager() {} |
| + |
| +// static |
| +void LogSourceAccessManager::SetRateLimitingTimeoutForTesting( |
| + const base::TimeDelta* timeout) { |
| + g_rate_limiting_timeout = timeout; |
| +} |
| + |
| +bool LogSourceAccessManager::AddExtension(const SourceAndExtension& key) { |
| + // emplace() returns a pair where the second element is a flag indicating |
| + // whether the entry was newly added. |
| + return active_keys_.emplace(key).second; |
| +} |
| + |
| +bool LogSourceAccessManager::RemoveExtension(const SourceAndExtension& key) { |
| + auto iter = active_keys_.find(key); |
|
tbarzic
2017/06/01 19:23:46
I'd prefer something like:
return active_keys_.er
Simon Que
2017/06/01 21:49:09
Done.
|
| + if (iter == active_keys_.end()) |
| + return false; |
| + |
| + active_keys_.erase(iter); |
| + return true; |
| +} |
| + |
| +size_t LogSourceAccessManager::GetNumActiveExtensionsForSource( |
| + api::feedback_private::LogSource source) const { |
| + size_t count = 0; |
| + // The stored entries are sorted first by source type, then by extension ID. |
| + // We can take advantage of this fact to avoid iterating over all elements. |
| + // Instead start from the first element that matches |source|, and end at the |
| + // first element that does not match |source| anymore. |
| + for (auto iter = active_keys_.lower_bound(SourceAndExtension(source, "")); |
| + iter != active_keys_.end() && iter->source == source; ++iter) { |
| + ++count; |
| + } |
| + return count; |
| +} |
| + |
| +bool LogSourceAccessManager::AccessSourceFromExtension( |
| + const SourceAndExtension& key) { |
| + base::TimeTicks last = GetLastExtensionAccessTime(key); |
| + base::TimeTicks now = tick_clock_->NowTicks(); |
| + if (last.is_null() || now >= last + GetMinTimeBetweenReads()) { |
| + last_access_times_[key] = now; |
| + return true; |
| + } |
| + return false; |
|
tbarzic
2017/06/01 19:23:46
nit: I'd switch this as:
if (!last.is_null() && no
Simon Que
2017/06/01 21:49:09
Done.
|
| +} |
| + |
| +base::TimeTicks LogSourceAccessManager::GetLastExtensionAccessTime( |
| + const SourceAndExtension& key) const { |
| + auto iter = last_access_times_.find(key); |
| + if (iter == last_access_times_.end()) |
| + return base::TimeTicks(); |
| + |
| + return iter->second; |
| +} |
| + |
| +base::Closure LogSourceAccessManager::GetUnregisterCallback( |
| + const SourceAndExtension& key) { |
| + return base::Bind(&LogSourceAccessManager::RemoveExtensionNoReturn, |
| + weak_factory_.GetWeakPtr(), key); |
| +} |
| + |
| +void LogSourceAccessManager::RemoveExtensionNoReturn( |
| + const SourceAndExtension& key) { |
| + RemoveExtension(key); |
| +} |
| + |
| +} // namespace extensions |