Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2050)

Unified Diff: chrome/browser/extensions/api/feedback_private/feedback_private_api.cc

Issue 2840103002: Add new API function: feedbackPrivate.readLogSource (Closed)
Patch Set: Addressed comments from Patch Set 4 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
index b13cf765fee1e86d05d99ee2bb3f87d5ef7e24a0..f6658230ff7ab36d12039b88e63eef63db2c74ac 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_private_api.cc
@@ -36,7 +36,11 @@
#include "url/url_util.h"
#if defined(OS_CHROMEOS)
+#include "base/strings/string_split.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/system_logs/single_log_source.h"
+#include "chrome/browser/extensions/api/feedback_private/single_log_source_factory.h"
+#include "extensions/browser/api/api_resource_manager.h"
#endif // defined(OS_CHROMEOS)
#if defined(OS_WIN)
@@ -66,6 +70,15 @@ constexpr base::Feature kSrtPromptOnFeedbackForm {
};
#endif
+#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)
+
} // namespace
namespace extensions {
@@ -82,6 +95,38 @@ using SystemInformationList =
static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>>::
DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
+#if defined(OS_CHROMEOS)
+using feedback_private::LogSource;
+using SingleLogSource = system_logs::SingleLogSource;
+using SupportedSource = system_logs::SingleLogSource::SupportedSource;
+using LogSourceResourceManager = ApiResourceManager<LogSourceResource>;
+
+// For managing API resources of type LogSourceResource.
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<LogSourceResourceManager>>::DestructorAtExit
+ g_log_source_resource_factory = LAZY_INSTANCE_INITIALIZER;
+
+// static
+template <>
+BrowserContextKeyedAPIFactory<LogSourceResourceManager>*
+LogSourceResourceManager::GetFactoryInstance() {
+ return g_log_source_resource_factory.Pointer();
+}
+
+// Converts from feedback_private::LogSource to SupportedSource.
+SupportedSource GetSupportedSourceType(LogSource source) {
+ switch (source) {
+ case feedback_private::LOG_SOURCE_MESSAGES:
+ return SupportedSource::kMessages;
+ case feedback_private::LOG_SOURCE_UI_LATEST:
+ return SupportedSource::kUiLatest;
+ case feedback_private::LOG_SOURCE_NONE:
+ DLOG(FATAL) << "Invalid log source type requested.";
+ return SingleLogSource::SupportedSource::kMessages;
+ }
+}
+#endif // defined(OS_CHROMEOS)
+
// static
BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>*
FeedbackPrivateAPI::GetFactoryInstance() {
@@ -89,8 +134,12 @@ FeedbackPrivateAPI::GetFactoryInstance() {
}
FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context)
- : browser_context_(context), service_(new FeedbackService()) {
-}
+ : browser_context_(context),
+ service_(new FeedbackService()),
+ access_manager_(new LogSourceAccessManager(
+ g_rate_limiting_timeout ? *g_rate_limiting_timeout
tbarzic 2017/05/25 22:46:44 can you just move this const to LogSourceAccessMan
Simon Que 2017/05/26 04:34:38 Done.
+ : base::TimeDelta::FromMilliseconds(
+ kDefaultRateLimitingTimeoutMs))) {}
FeedbackPrivateAPI::~FeedbackPrivateAPI() {
delete service_;
@@ -259,6 +308,129 @@ void FeedbackPrivateGetSystemInformationFunction::OnCompleted(
feedback_private::GetSystemInformation::Results::Create(sys_info_list)));
}
+#if defined(OS_CHROMEOS)
+// static
+void FeedbackPrivateReadLogSourceFunction::SetRateLimitingTimeoutForTesting(
+ const base::TimeDelta* timeout) {
+ g_rate_limiting_timeout = timeout;
+}
+#endif // defined(OS_CHROMEOS)
+
+ExtensionFunction::ResponseAction FeedbackPrivateReadLogSourceFunction::Run() {
+#if defined(OS_CHROMEOS)
+ using Params = feedback_private::ReadLogSource::Params;
+ std::unique_ptr<Params> api_params = Params::Create(*args_);
+
+ int reader_id =
+ api_params->params.reader_id ? *api_params->params.reader_id : 0;
+ LogSource source = api_params->params.source;
+
+ LogSourceResource* resource = GetOrCreateLogSourceResource(reader_id, source);
+ if (!resource)
+ return RespondNow(
+ Error("Unable to get existing or create new log source."));
+
+ // Enforce the rules: rate-limit access to the source from the current
+ // extension. If not enough time has elapsed since the last access, do not
+ // read from the source, but instead return an empty response. From the
+ // caller's perspective, there is no new data. There is no need for the caller
+ // to keep track of the time since last access.
+ LogSourceAccessManager* log_source_manager =
+ FeedbackPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->GetLogSourceAccessManager();
+ DCHECK(log_source_manager);
+ if (!log_source_manager->AccessSourceFromExtension(
+ LogSourceAccessManager::SourceAndExtension(source, extension_id())))
tbarzic 2017/05/25 22:46:44 add {}
Simon Que 2017/05/26 04:34:38 Done.
+ return RespondNow(
+ ArgumentList(feedback_private::ReadLogSource::Results::Create(
+ 0, std::vector<std::string>())));
+
+ // Now we are ready to access the log source.
+ resource->GetLogSource()->Fetch(
+ base::Bind(&FeedbackPrivateReadLogSourceFunction::OnCompleted, this,
+ source, reader_id, api_params->params.incremental));
+
+ return RespondLater();
+#else
+ return RespondNow(Error("API function is not supported."));
+#endif // defined(OS_CHROMEOS)
+}
+
+#if defined(OS_CHROMEOS)
+LogSourceResource*
+FeedbackPrivateReadLogSourceFunction::GetOrCreateLogSourceResource(
+ int reader_id,
+ LogSource source) {
+ LogSourceResourceManager* resource_manager =
+ LogSourceResourceManager::Get(browser_context());
+ DCHECK(resource_manager);
+
+ LogSourceResource* resource = nullptr;
+ // If the caller passed in a valid ID, look up the ID in the resource manager.
+ if (reader_id > 0) {
+ resource = resource_manager->Get(extension_id(), reader_id);
+ if (!resource)
+ return nullptr;
tbarzic 2017/05/25 22:46:44 Shouldn't you just return resource here? i.e. if (
Simon Que 2017/05/26 04:34:38 Done.
+ }
+
+ LogSourceAccessManager* log_source_manager =
+ FeedbackPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->GetLogSourceAccessManager();
+ DCHECK(log_source_manager);
+
+ LogSourceAccessManager::SourceAndExtension source_and_extension(
+ source, extension_id());
+
+ // If caller passed in |reader_id| == 0, create a new SingleLogSource.
+
+ // Enforce the rules: Do not create a new SingleLogSource if there was
+ // already one created for |source_and_extension|.
+ if (!log_source_manager->AddExtension(source_and_extension))
+ return nullptr;
+
+ SupportedSource source_type = GetSupportedSourceType(source);
+ std::unique_ptr<LogSourceResource> new_resource(new LogSourceResource(
tbarzic 2017/05/25 22:46:45 prefer MakeUnique over new
Simon Que 2017/05/26 04:34:38 Done.
+ extension_id(),
+ SingleLogSourceFactory::CreateSingleLogSource(source_type).release(),
+ log_source_manager->GetUnregisterCallback(source_and_extension)));
+ resource = new_resource.get();
+
+ reader_id = resource_manager->Add(new_resource.release());
tbarzic 2017/05/25 22:46:45 you don't use this anywhere
Simon Que 2017/05/26 04:34:38 Done.
+
+ return resource;
+}
+
+void FeedbackPrivateReadLogSourceFunction::OnCompleted(
+ LogSource source,
+ int reader_id,
+ bool incremental,
+ system_logs::SystemLogsResponse* response) {
+ std::vector<std::string> result;
+ for (const std::pair<std::string, std::string>& pair : *response) {
+ // TODO(sque): Use std::move?
+ std::vector<std::string> new_lines = base::SplitString(
+ pair.second, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ result.reserve(result.size() + new_lines.size());
+ result.insert(result.end(), new_lines.begin(), new_lines.end());
+ }
+
+ // If the API call requested a non-incremental access, clean up the
+ // SingleLogSource by removing its API resource.
+ if (!incremental) {
+ LogSourceResourceManager::Get(browser_context())
+ ->Remove(extension_id(), reader_id);
+ // Must return reader_id=0 when the resource has been deleted.
+ reader_id = 0;
+ }
+
+ Respond(ArgumentList(
+ feedback_private::ReadLogSource::Results::Create(reader_id, result)));
+}
+
+#endif // defined(OS_CHROMEOS)
+
bool FeedbackPrivateSendFeedbackFunction::RunAsync() {
std::unique_ptr<feedback_private::SendFeedback::Params> params(
feedback_private::SendFeedback::Params::Create(*args_));

Powered by Google App Engine
This is Rietveld 408576698