Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h" | 5 #include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 #include "chrome/grit/generated_resources.h" | 29 #include "chrome/grit/generated_resources.h" |
| 30 #include "components/feedback/tracing_manager.h" | 30 #include "components/feedback/tracing_manager.h" |
| 31 #include "components/signin/core/browser/signin_manager.h" | 31 #include "components/signin/core/browser/signin_manager.h" |
| 32 #include "components/strings/grit/components_strings.h" | 32 #include "components/strings/grit/components_strings.h" |
| 33 #include "extensions/browser/event_router.h" | 33 #include "extensions/browser/event_router.h" |
| 34 #include "ui/base/l10n/l10n_util.h" | 34 #include "ui/base/l10n/l10n_util.h" |
| 35 #include "ui/base/webui/web_ui_util.h" | 35 #include "ui/base/webui/web_ui_util.h" |
| 36 #include "url/url_util.h" | 36 #include "url/url_util.h" |
| 37 | 37 |
| 38 #if defined(OS_CHROMEOS) | 38 #if defined(OS_CHROMEOS) |
| 39 #include "base/strings/string_split.h" | |
| 39 #include "chrome/browser/chromeos/arc/arc_util.h" | 40 #include "chrome/browser/chromeos/arc/arc_util.h" |
| 41 #include "chrome/browser/chromeos/system_logs/single_log_source.h" | |
| 42 #include "chrome/browser/extensions/api/feedback_private/single_log_source_facto ry.h" | |
| 43 #include "extensions/browser/api/api_resource_manager.h" | |
| 40 #endif // defined(OS_CHROMEOS) | 44 #endif // defined(OS_CHROMEOS) |
| 41 | 45 |
| 42 #if defined(OS_WIN) | 46 #if defined(OS_WIN) |
| 43 #include "base/feature_list.h" | 47 #include "base/feature_list.h" |
| 44 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h" | 48 #include "chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.h" |
| 45 #endif | 49 #endif |
| 46 | 50 |
| 47 using extensions::api::feedback_private::SystemInformation; | 51 using extensions::api::feedback_private::SystemInformation; |
| 48 using feedback::FeedbackData; | 52 using feedback::FeedbackData; |
| 49 | 53 |
| 50 namespace { | 54 namespace { |
| 51 | 55 |
| 52 // Getting the filename of a blob prepends a "C:\fakepath" to the filename. | 56 // Getting the filename of a blob prepends a "C:\fakepath" to the filename. |
| 53 // This is undesirable, strip it if it exists. | 57 // This is undesirable, strip it if it exists. |
| 54 std::string StripFakepath(const std::string& path) { | 58 std::string StripFakepath(const std::string& path) { |
| 55 const char kFakePathStr[] = "C:\\fakepath\\"; | 59 const char kFakePathStr[] = "C:\\fakepath\\"; |
| 56 if (base::StartsWith(path, kFakePathStr, | 60 if (base::StartsWith(path, kFakePathStr, |
| 57 base::CompareCase::INSENSITIVE_ASCII)) | 61 base::CompareCase::INSENSITIVE_ASCII)) |
| 58 return path.substr(arraysize(kFakePathStr) - 1); | 62 return path.substr(arraysize(kFakePathStr) - 1); |
| 59 return path; | 63 return path; |
| 60 } | 64 } |
| 61 | 65 |
| 62 #if defined(OS_WIN) | 66 #if defined(OS_WIN) |
| 63 // Allows enabling/disabling SRT Prompt as a Variations feature. | 67 // Allows enabling/disabling SRT Prompt as a Variations feature. |
| 64 constexpr base::Feature kSrtPromptOnFeedbackForm { | 68 constexpr base::Feature kSrtPromptOnFeedbackForm { |
| 65 "SrtPromptOnFeedbackForm", base::FEATURE_DISABLED_BY_DEFAULT | 69 "SrtPromptOnFeedbackForm", base::FEATURE_DISABLED_BY_DEFAULT |
| 66 }; | 70 }; |
| 67 #endif | 71 #endif |
| 68 | 72 |
| 73 #if defined(OS_CHROMEOS) | |
| 74 // The minimum time between consecutive reads of a log source by a particular | |
| 75 // extension. | |
| 76 const int kDefaultRateLimitingTimeoutMs = 1000; | |
| 77 | |
| 78 // If this is null, then |kDefaultRateLimitingTimeoutMs| is used as the timeout. | |
| 79 const base::TimeDelta* g_rate_limiting_timeout = nullptr; | |
| 80 #endif // defined(OS_CHROMEOS) | |
| 81 | |
| 69 } // namespace | 82 } // namespace |
| 70 | 83 |
| 71 namespace extensions { | 84 namespace extensions { |
| 72 | 85 |
| 73 namespace feedback_private = api::feedback_private; | 86 namespace feedback_private = api::feedback_private; |
| 74 | 87 |
| 75 using feedback_private::SystemInformation; | 88 using feedback_private::SystemInformation; |
| 76 using feedback_private::FeedbackInfo; | 89 using feedback_private::FeedbackInfo; |
| 77 using feedback_private::FeedbackFlow; | 90 using feedback_private::FeedbackFlow; |
| 78 | 91 |
| 79 using SystemInformationList = | 92 using SystemInformationList = |
| 80 std::vector<api::feedback_private::SystemInformation>; | 93 std::vector<api::feedback_private::SystemInformation>; |
| 81 | 94 |
| 82 static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>>:: | 95 static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>>:: |
| 83 DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER; | 96 DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER; |
| 84 | 97 |
| 98 #if defined(OS_CHROMEOS) | |
| 99 using feedback_private::LogSource; | |
| 100 using SingleLogSource = system_logs::SingleLogSource; | |
| 101 using SupportedSource = system_logs::SingleLogSource::SupportedSource; | |
| 102 using LogSourceResourceManager = ApiResourceManager<LogSourceResource>; | |
| 103 | |
| 104 // For managing API resources of type LogSourceResource. | |
| 105 static base::LazyInstance< | |
| 106 BrowserContextKeyedAPIFactory<LogSourceResourceManager>>::DestructorAtExit | |
| 107 g_log_source_resource_factory = LAZY_INSTANCE_INITIALIZER; | |
| 108 | |
| 109 // static | |
| 110 template <> | |
| 111 BrowserContextKeyedAPIFactory<LogSourceResourceManager>* | |
| 112 LogSourceResourceManager::GetFactoryInstance() { | |
| 113 return g_log_source_resource_factory.Pointer(); | |
| 114 } | |
| 115 | |
| 116 // Converts from feedback_private::LogSource to SupportedSource. | |
| 117 SupportedSource GetSupportedSourceType(LogSource source) { | |
| 118 switch (source) { | |
| 119 case feedback_private::LOG_SOURCE_MESSAGES: | |
| 120 return SupportedSource::kMessages; | |
| 121 case feedback_private::LOG_SOURCE_UI_LATEST: | |
| 122 return SupportedSource::kUiLatest; | |
| 123 case feedback_private::LOG_SOURCE_NONE: | |
| 124 DLOG(FATAL) << "Invalid log source type requested."; | |
| 125 return SingleLogSource::SupportedSource::kMessages; | |
| 126 } | |
| 127 } | |
| 128 #endif // defined(OS_CHROMEOS) | |
| 129 | |
| 85 // static | 130 // static |
| 86 BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>* | 131 BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>* |
| 87 FeedbackPrivateAPI::GetFactoryInstance() { | 132 FeedbackPrivateAPI::GetFactoryInstance() { |
| 88 return g_factory.Pointer(); | 133 return g_factory.Pointer(); |
| 89 } | 134 } |
| 90 | 135 |
| 91 FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context) | 136 FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context) |
| 92 : browser_context_(context), service_(new FeedbackService()) { | 137 : browser_context_(context), |
| 93 } | 138 service_(new FeedbackService()), |
| 139 access_manager_(new LogSourceAccessManager( | |
| 140 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.
| |
| 141 : base::TimeDelta::FromMilliseconds( | |
| 142 kDefaultRateLimitingTimeoutMs))) {} | |
| 94 | 143 |
| 95 FeedbackPrivateAPI::~FeedbackPrivateAPI() { | 144 FeedbackPrivateAPI::~FeedbackPrivateAPI() { |
| 96 delete service_; | 145 delete service_; |
| 97 service_ = NULL; | 146 service_ = NULL; |
| 98 } | 147 } |
| 99 | 148 |
| 100 FeedbackService* FeedbackPrivateAPI::GetService() const { | 149 FeedbackService* FeedbackPrivateAPI::GetService() const { |
| 101 return service_; | 150 return service_; |
| 102 } | 151 } |
| 103 | 152 |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 sys_info_entry.key = std::move(itr.first); | 301 sys_info_entry.key = std::move(itr.first); |
| 253 sys_info_entry.value = std::move(itr.second); | 302 sys_info_entry.value = std::move(itr.second); |
| 254 sys_info_list.emplace_back(std::move(sys_info_entry)); | 303 sys_info_list.emplace_back(std::move(sys_info_entry)); |
| 255 } | 304 } |
| 256 } | 305 } |
| 257 | 306 |
| 258 Respond(ArgumentList( | 307 Respond(ArgumentList( |
| 259 feedback_private::GetSystemInformation::Results::Create(sys_info_list))); | 308 feedback_private::GetSystemInformation::Results::Create(sys_info_list))); |
| 260 } | 309 } |
| 261 | 310 |
| 311 #if defined(OS_CHROMEOS) | |
| 312 // static | |
| 313 void FeedbackPrivateReadLogSourceFunction::SetRateLimitingTimeoutForTesting( | |
| 314 const base::TimeDelta* timeout) { | |
| 315 g_rate_limiting_timeout = timeout; | |
| 316 } | |
| 317 #endif // defined(OS_CHROMEOS) | |
| 318 | |
| 319 ExtensionFunction::ResponseAction FeedbackPrivateReadLogSourceFunction::Run() { | |
| 320 #if defined(OS_CHROMEOS) | |
| 321 using Params = feedback_private::ReadLogSource::Params; | |
| 322 std::unique_ptr<Params> api_params = Params::Create(*args_); | |
| 323 | |
| 324 int reader_id = | |
| 325 api_params->params.reader_id ? *api_params->params.reader_id : 0; | |
| 326 LogSource source = api_params->params.source; | |
| 327 | |
| 328 LogSourceResource* resource = GetOrCreateLogSourceResource(reader_id, source); | |
| 329 if (!resource) | |
| 330 return RespondNow( | |
| 331 Error("Unable to get existing or create new log source.")); | |
| 332 | |
| 333 // Enforce the rules: rate-limit access to the source from the current | |
| 334 // extension. If not enough time has elapsed since the last access, do not | |
| 335 // read from the source, but instead return an empty response. From the | |
| 336 // caller's perspective, there is no new data. There is no need for the caller | |
| 337 // to keep track of the time since last access. | |
| 338 LogSourceAccessManager* log_source_manager = | |
| 339 FeedbackPrivateAPI::GetFactoryInstance() | |
| 340 ->Get(browser_context()) | |
| 341 ->GetLogSourceAccessManager(); | |
| 342 DCHECK(log_source_manager); | |
| 343 if (!log_source_manager->AccessSourceFromExtension( | |
| 344 LogSourceAccessManager::SourceAndExtension(source, extension_id()))) | |
|
tbarzic
2017/05/25 22:46:44
add {}
Simon Que
2017/05/26 04:34:38
Done.
| |
| 345 return RespondNow( | |
| 346 ArgumentList(feedback_private::ReadLogSource::Results::Create( | |
| 347 0, std::vector<std::string>()))); | |
| 348 | |
| 349 // Now we are ready to access the log source. | |
| 350 resource->GetLogSource()->Fetch( | |
| 351 base::Bind(&FeedbackPrivateReadLogSourceFunction::OnCompleted, this, | |
| 352 source, reader_id, api_params->params.incremental)); | |
| 353 | |
| 354 return RespondLater(); | |
| 355 #else | |
| 356 return RespondNow(Error("API function is not supported.")); | |
| 357 #endif // defined(OS_CHROMEOS) | |
| 358 } | |
| 359 | |
| 360 #if defined(OS_CHROMEOS) | |
| 361 LogSourceResource* | |
| 362 FeedbackPrivateReadLogSourceFunction::GetOrCreateLogSourceResource( | |
| 363 int reader_id, | |
| 364 LogSource source) { | |
| 365 LogSourceResourceManager* resource_manager = | |
| 366 LogSourceResourceManager::Get(browser_context()); | |
| 367 DCHECK(resource_manager); | |
| 368 | |
| 369 LogSourceResource* resource = nullptr; | |
| 370 // If the caller passed in a valid ID, look up the ID in the resource manager. | |
| 371 if (reader_id > 0) { | |
| 372 resource = resource_manager->Get(extension_id(), reader_id); | |
| 373 if (!resource) | |
| 374 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.
| |
| 375 } | |
| 376 | |
| 377 LogSourceAccessManager* log_source_manager = | |
| 378 FeedbackPrivateAPI::GetFactoryInstance() | |
| 379 ->Get(browser_context()) | |
| 380 ->GetLogSourceAccessManager(); | |
| 381 DCHECK(log_source_manager); | |
| 382 | |
| 383 LogSourceAccessManager::SourceAndExtension source_and_extension( | |
| 384 source, extension_id()); | |
| 385 | |
| 386 // If caller passed in |reader_id| == 0, create a new SingleLogSource. | |
| 387 | |
| 388 // Enforce the rules: Do not create a new SingleLogSource if there was | |
| 389 // already one created for |source_and_extension|. | |
| 390 if (!log_source_manager->AddExtension(source_and_extension)) | |
| 391 return nullptr; | |
| 392 | |
| 393 SupportedSource source_type = GetSupportedSourceType(source); | |
| 394 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.
| |
| 395 extension_id(), | |
| 396 SingleLogSourceFactory::CreateSingleLogSource(source_type).release(), | |
| 397 log_source_manager->GetUnregisterCallback(source_and_extension))); | |
| 398 resource = new_resource.get(); | |
| 399 | |
| 400 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.
| |
| 401 | |
| 402 return resource; | |
| 403 } | |
| 404 | |
| 405 void FeedbackPrivateReadLogSourceFunction::OnCompleted( | |
| 406 LogSource source, | |
| 407 int reader_id, | |
| 408 bool incremental, | |
| 409 system_logs::SystemLogsResponse* response) { | |
| 410 std::vector<std::string> result; | |
| 411 for (const std::pair<std::string, std::string>& pair : *response) { | |
| 412 // TODO(sque): Use std::move? | |
| 413 std::vector<std::string> new_lines = base::SplitString( | |
| 414 pair.second, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 415 result.reserve(result.size() + new_lines.size()); | |
| 416 result.insert(result.end(), new_lines.begin(), new_lines.end()); | |
| 417 } | |
| 418 | |
| 419 // If the API call requested a non-incremental access, clean up the | |
| 420 // SingleLogSource by removing its API resource. | |
| 421 if (!incremental) { | |
| 422 LogSourceResourceManager::Get(browser_context()) | |
| 423 ->Remove(extension_id(), reader_id); | |
| 424 // Must return reader_id=0 when the resource has been deleted. | |
| 425 reader_id = 0; | |
| 426 } | |
| 427 | |
| 428 Respond(ArgumentList( | |
| 429 feedback_private::ReadLogSource::Results::Create(reader_id, result))); | |
| 430 } | |
| 431 | |
| 432 #endif // defined(OS_CHROMEOS) | |
| 433 | |
| 262 bool FeedbackPrivateSendFeedbackFunction::RunAsync() { | 434 bool FeedbackPrivateSendFeedbackFunction::RunAsync() { |
| 263 std::unique_ptr<feedback_private::SendFeedback::Params> params( | 435 std::unique_ptr<feedback_private::SendFeedback::Params> params( |
| 264 feedback_private::SendFeedback::Params::Create(*args_)); | 436 feedback_private::SendFeedback::Params::Create(*args_)); |
| 265 EXTENSION_FUNCTION_VALIDATE(params); | 437 EXTENSION_FUNCTION_VALIDATE(params); |
| 266 | 438 |
| 267 const FeedbackInfo &feedback_info = params->feedback; | 439 const FeedbackInfo &feedback_info = params->feedback; |
| 268 | 440 |
| 269 // Populate feedback data. | 441 // Populate feedback data. |
| 270 scoped_refptr<FeedbackData> feedback_data(new FeedbackData()); | 442 scoped_refptr<FeedbackData> feedback_data(new FeedbackData()); |
| 271 feedback_data->set_context(GetProfile()); | 443 feedback_data->set_context(GetProfile()); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 case feedback_private::SRT_PROMPT_RESULT_CLOSED: | 530 case feedback_private::SRT_PROMPT_RESULT_CLOSED: |
| 359 base::RecordAction(base::UserMetricsAction("Feedback.SrtPromptClosed")); | 531 base::RecordAction(base::UserMetricsAction("Feedback.SrtPromptClosed")); |
| 360 break; | 532 break; |
| 361 default: | 533 default: |
| 362 return RespondNow(Error("Invalid arugment.")); | 534 return RespondNow(Error("Invalid arugment.")); |
| 363 } | 535 } |
| 364 return RespondNow(NoArguments()); | 536 return RespondNow(NoArguments()); |
| 365 } | 537 } |
| 366 | 538 |
| 367 } // namespace extensions | 539 } // namespace extensions |
| OLD | NEW |