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

Unified Diff: components/feedback/feedback_common.cc

Issue 296173003: Refactor FeedbackData and add tests. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: add feedback.gypi to OWNERS file Created 6 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
« no previous file with comments | « components/feedback/feedback_common.h ('k') | components/feedback/feedback_common_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/feedback/feedback_common.cc
diff --git a/components/feedback/feedback_common.cc b/components/feedback/feedback_common.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e3e27480c7a0c90805a1c316ef4ae35dbb66ef8b
--- /dev/null
+++ b/components/feedback/feedback_common.cc
@@ -0,0 +1,214 @@
+// Copyright 2014 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 "feedback_common.h"
+
+#include "base/strings/string_util.h"
+#include "components/feedback/proto/common.pb.h"
+#include "components/feedback/proto/dom.pb.h"
+#include "components/feedback/proto/extension.pb.h"
+#include "components/feedback/proto/math.pb.h"
+
+namespace {
+
+const char kMultilineIndicatorString[] = "<multiline>\n";
+const char kMultilineStartString[] = "---------- START ----------\n";
+const char kMultilineEndString[] = "---------- END ----------\n\n";
+
+const size_t kFeedbackMaxLength = 4 * 1024;
+const size_t kFeedbackMaxLineCount = 40;
+
+const base::FilePath::CharType kLogsFilename[] =
+ FILE_PATH_LITERAL("system_logs.txt");
+const char kLogsAttachmentName[] = "system_logs.zip";
+
+const char kZipExt[] = ".zip";
+
+const char kPngMimeType[] = "image/png";
+const char kArbitraryMimeType[] = "application/octet-stream";
+
+// Converts the system logs into a string that we can compress and send
+// with the report. This method only converts those logs that we want in
+// the compressed zip file sent with the report, hence it ignores any logs
+// below the size threshold of what we want compressed.
+std::string* LogsToString(const FeedbackCommon::SystemLogsMap& sys_info) {
+ std::string* syslogs_string = new std::string;
+ for (FeedbackCommon::SystemLogsMap::const_iterator it = sys_info.begin();
+ it != sys_info.end();
+ ++it) {
+ std::string key = it->first;
+ std::string value = it->second;
+
+ if (FeedbackCommon::BelowCompressionThreshold(value))
+ continue;
+
+ base::TrimString(key, "\n ", &key);
+ base::TrimString(value, "\n ", &value);
+
+ if (value.find("\n") != std::string::npos) {
+ syslogs_string->append(key + "=" + kMultilineIndicatorString +
+ kMultilineStartString + value + "\n" +
+ kMultilineEndString);
+ } else {
+ syslogs_string->append(key + "=" + value + "\n");
+ }
+ }
+ return syslogs_string;
+}
+
+void AddFeedbackData(userfeedback::ExtensionSubmit* feedback_data,
+ const std::string& key,
+ const std::string& value) {
+ // Don't bother with empty keys or values.
+ if (key.empty() || value.empty())
+ return;
+ // Create log_value object and add it to the web_data object.
+ userfeedback::ProductSpecificData log_value;
+ log_value.set_key(key);
+ log_value.set_value(value);
+ userfeedback::WebData* web_data = feedback_data->mutable_web_data();
+ *(web_data->add_product_specific_data()) = log_value;
+}
+
+// Adds data as an attachment to feedback_data if the data is non-empty.
+void AddAttachment(userfeedback::ExtensionSubmit* feedback_data,
+ const char* name,
+ const std::string& data) {
+ if (data.empty())
+ return;
+
+ userfeedback::ProductSpecificBinaryData* attachment =
+ feedback_data->add_product_specific_binary_data();
+ attachment->set_mime_type(kArbitraryMimeType);
+ attachment->set_name(name);
+ attachment->set_data(data);
+}
+
+} // namespace
+
+FeedbackCommon::AttachedFile::AttachedFile(const std::string& filename,
+ scoped_ptr<std::string> data)
+ : name(filename), data(data.Pass()) {}
+
+FeedbackCommon::AttachedFile::~AttachedFile() {}
+
+
+FeedbackCommon::FeedbackCommon() : product_id_(0) {}
+
+FeedbackCommon::~FeedbackCommon() {}
+
+// static
+bool FeedbackCommon::BelowCompressionThreshold(const std::string& content) {
+ if (content.length() > kFeedbackMaxLength)
+ return false;
+ const size_t line_count = std::count(content.begin(), content.end(), '\n');
+ if (line_count > kFeedbackMaxLineCount)
+ return false;
+ return true;
+}
+
+void FeedbackCommon::CompressFile(const base::FilePath& filename,
+ const std::string& zipname,
+ scoped_ptr<std::string> data) {
+ AttachedFile* file = new AttachedFile(
+ zipname, scoped_ptr<std::string>(new std::string()));
+ if (file->name.empty()) {
+ // We need to use the UTF8Unsafe methods here to accomodate Windows, which
+ // uses wide strings to store filepaths.
+ file->name = filename.BaseName().AsUTF8Unsafe();
+ file->name.append(kZipExt);
+ }
+ if (feedback_util::ZipString(filename, *(data.get()), file->data.get())) {
+ base::AutoLock lock(attachments_lock_);
+ attachments_.push_back(file);
+ } else {
+ delete file;
+ }
+}
+
+void FeedbackCommon::AddFile(const std::string& filename,
+ scoped_ptr<std::string> data) {
+ base::AutoLock lock(attachments_lock_);
+ attachments_.push_back(new AttachedFile(filename, data.Pass()));
+}
+
+void FeedbackCommon::AddLog(const std::string& name, const std::string& value) {
+ if (!logs_.get())
+ logs_ = scoped_ptr<SystemLogsMap>(new SystemLogsMap);
+ (*logs_.get())[name] = value;
+}
+
+void FeedbackCommon::AddLogs(scoped_ptr<SystemLogsMap> logs) {
+ if (logs_) {
+ logs_->insert(logs->begin(), logs->end());
+ } else {
+ logs_ = logs.Pass();
+ }
+}
+
+void FeedbackCommon::CompressLogs() {
+ if (!logs_)
+ return;
+ std::string* logs = LogsToString(*logs_.get());
+ if (!logs->empty())
+ CompressFile(
+ base::FilePath(kLogsFilename), kLogsAttachmentName,
+ scoped_ptr<std::string>(logs));
+}
+
+void FeedbackCommon::AddFilesAndLogsToReport(
+ userfeedback::ExtensionSubmit* feedback_data) const {
+ if (sys_info()) {
+ for (FeedbackCommon::SystemLogsMap::const_iterator i = sys_info()->begin();
+ i != sys_info()->end();
+ ++i) {
+ if (BelowCompressionThreshold(i->second))
+ AddFeedbackData(feedback_data, i->first, i->second);
+ }
+ }
+
+ for (size_t i = 0; i < attachments(); i++) {
+ const AttachedFile* file = attachment(i);
+ AddAttachment(feedback_data, file->name.c_str(), *file->data.get());
+ }
+}
+
+void FeedbackCommon::PrepareReport(
+ userfeedback::ExtensionSubmit* feedback_data) const {
+ // Unused field, needs to be 0 though.
+ feedback_data->set_type_id(0);
+ feedback_data->set_product_id(product_id_);
+
+ userfeedback::CommonData* common_data = feedback_data->mutable_common_data();
+ // We're not using gaia ids, we're using the e-mail field instead.
+ common_data->set_gaia_id(0);
+ common_data->set_user_email(user_email());
+ common_data->set_description(description());
+ common_data->set_source_description_language(locale());
+
+ userfeedback::WebData* web_data = feedback_data->mutable_web_data();
+ web_data->set_url(page_url());
+ web_data->mutable_navigator()->set_user_agent(user_agent());
+
+ AddFilesAndLogsToReport(feedback_data);
+
+ if (image() && image()->size()) {
+ userfeedback::PostedScreenshot screenshot;
+ screenshot.set_mime_type(kPngMimeType);
+
+ // Set that we 'have' dimensions of the screenshot. These dimensions are
+ // ignored by the server but are a 'required' field in the protobuf.
+ userfeedback::Dimensions dimensions;
+ dimensions.set_width(0.0);
+ dimensions.set_height(0.0);
+
+ *(screenshot.mutable_dimensions()) = dimensions;
+ screenshot.set_binary_content(*image());
+
+ *(feedback_data->mutable_screenshot()) = screenshot;
+ }
+
+ if (category_tag().size())
+ feedback_data->set_bucket(category_tag());
+}
« no previous file with comments | « components/feedback/feedback_common.h ('k') | components/feedback/feedback_common_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698