| 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..3fc361075627863350abc1f02448500ed77e677d 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)
|
| @@ -82,6 +86,25 @@ 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;
|
| +
|
| +// 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 +112,9 @@ FeedbackPrivateAPI::GetFactoryInstance() {
|
| }
|
|
|
| FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context)
|
| - : browser_context_(context), service_(new FeedbackService()) {
|
| -}
|
| + : browser_context_(context),
|
| + service_(new FeedbackService()),
|
| + log_source_access_manager_(new LogSourceAccessManager) {}
|
|
|
| FeedbackPrivateAPI::~FeedbackPrivateAPI() {
|
| delete service_;
|
| @@ -259,6 +283,121 @@ void FeedbackPrivateGetSystemInformationFunction::OnCompleted(
|
| feedback_private::GetSystemInformation::Results::Create(sys_info_list)));
|
| }
|
|
|
| +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())
|
| + ->log_source_access_manager();
|
| + DCHECK(log_source_manager);
|
| + if (!log_source_manager->AccessSourceFromExtension(
|
| + LogSourceAccessManager::SourceAndExtension(source, extension_id()))) {
|
| + 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) {
|
| + ApiResourceManager<LogSourceResource>* resource_manager =
|
| + ApiResourceManager<LogSourceResource>::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)
|
| + return resource_manager->Get(extension_id(), *reader_id);
|
| +
|
| + LogSourceAccessManager* log_source_manager =
|
| + FeedbackPrivateAPI::GetFactoryInstance()
|
| + ->Get(browser_context())
|
| + ->log_source_access_manager();
|
| + 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 =
|
| + base::MakeUnique<LogSourceResource>(
|
| + 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());
|
| +
|
| + 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) {
|
| + ApiResourceManager<LogSourceResource>::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_));
|
|
|