summaryrefslogtreecommitdiffstats
path: root/chrome/browser/feedback
diff options
context:
space:
mode:
authorrkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 22:46:03 +0000
committerrkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 22:46:03 +0000
commit4abf1a4814b4639ca3e21bdcc89c876dec380072 (patch)
tree061a53638b944628482ec9a6ebbebc01840e9b6d /chrome/browser/feedback
parent4799e5b86eef5fe9281baec4def22e5092dc2b0d (diff)
downloadchromium_src-4abf1a4814b4639ca3e21bdcc89c876dec380072.zip
chromium_src-4abf1a4814b4639ca3e21bdcc89c876dec380072.tar.gz
chromium_src-4abf1a4814b4639ca3e21bdcc89c876dec380072.tar.bz2
Add feedback uploader to upload reports in a sequenced manner with retries.
This is the first part of the CL that will enable re-sending feedback reports that were sent when the user was offline, across sessions. R=jcivelli@chromium.org, zork@chromium.org BUG=249853 Review URL: https://codereview.chromium.org/116863002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241962 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/feedback')
-rw-r--r--chrome/browser/feedback/feedback_uploader.cc130
-rw-r--r--chrome/browser/feedback/feedback_uploader.h76
-rw-r--r--chrome/browser/feedback/feedback_uploader_delegate.cc65
-rw-r--r--chrome/browser/feedback/feedback_uploader_delegate.h42
-rw-r--r--chrome/browser/feedback/feedback_uploader_factory.cc37
-rw-r--r--chrome/browser/feedback/feedback_uploader_factory.h45
-rw-r--r--chrome/browser/feedback/feedback_uploader_unittest.cc131
-rw-r--r--chrome/browser/feedback/feedback_util.cc132
8 files changed, 533 insertions, 125 deletions
diff --git a/chrome/browser/feedback/feedback_uploader.cc b/chrome/browser/feedback/feedback_uploader.cc
new file mode 100644
index 0000000..2cfbc03
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader.cc
@@ -0,0 +1,130 @@
+// Copyright 2013 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/feedback/feedback_uploader.h"
+
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/task_runner_util.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_fetcher.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+
+namespace feedback {
+namespace {
+
+const char kFeedbackPostUrl[] =
+ "https://www.google.com/tools/feedback/chrome/__submit";
+const char kProtBufMimeType[] = "application/x-protobuf";
+
+const base::TimeDelta kRetryDelay = base::TimeDelta::FromMinutes(60);
+
+} // namespace
+
+struct FeedbackReport {
+ FeedbackReport(const base::Time& upload_at, scoped_ptr<std::string> data)
+ : upload_at(upload_at), data(data.Pass()) {}
+
+ FeedbackReport(const FeedbackReport& report) {
+ upload_at = report.upload_at;
+ data = report.data.Pass();
+ }
+
+ FeedbackReport& operator=(const FeedbackReport& report) {
+ upload_at = report.upload_at;
+ data = report.data.Pass();
+ return *this;
+ }
+
+ base::Time upload_at; // Upload this report at or after this time.
+ mutable scoped_ptr<std::string> data;
+};
+
+bool FeedbackUploader::ReportsUploadTimeComparator::operator()(
+ const FeedbackReport& a, const FeedbackReport& b) const {
+ return a.upload_at > b.upload_at;
+}
+
+FeedbackUploader::FeedbackUploader(content::BrowserContext* context)
+ : context_(context),
+ retry_delay_(kRetryDelay) {
+ CHECK(context_);
+ dispatch_callback_ = base::Bind(&FeedbackUploader::DispatchReport,
+ AsWeakPtr());
+}
+
+FeedbackUploader::~FeedbackUploader() {
+}
+
+void FeedbackUploader::QueueReport(scoped_ptr<std::string> data) {
+ reports_queue_.push(FeedbackReport(base::Time::Now(), data.Pass()));
+ UpdateUploadTimer();
+}
+
+void FeedbackUploader::DispatchReport(scoped_ptr<std::string> data) {
+ GURL post_url;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFeedbackServer))
+ post_url = GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kFeedbackServer));
+ else
+ post_url = GURL(kFeedbackPostUrl);
+
+ // Save the report data pointer since the report.Pass() in the next statement
+ // will invalidate the scoper.
+ std::string* data_ptr = data.get();
+ net::URLFetcher* fetcher = net::URLFetcher::Create(
+ post_url, net::URLFetcher::POST,
+ new FeedbackUploaderDelegate(
+ data.Pass(),
+ base::Bind(&FeedbackUploader::UpdateUploadTimer, AsWeakPtr()),
+ base::Bind(&FeedbackUploader::RetryReport, AsWeakPtr())));
+
+ fetcher->SetUploadData(std::string(kProtBufMimeType), *data_ptr);
+ fetcher->SetRequestContext(context_->GetRequestContext());
+ fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
+ net::LOAD_DO_NOT_SEND_COOKIES);
+ fetcher->Start();
+}
+
+void FeedbackUploader::UpdateUploadTimer() {
+ if (reports_queue_.empty())
+ return;
+
+ const FeedbackReport& report = reports_queue_.top();
+ base::Time now = base::Time::Now();
+ if (report.upload_at <= now) {
+ scoped_ptr<std::string> data = report.data.Pass();
+ reports_queue_.pop();
+ dispatch_callback_.Run(data.Pass());
+ } else {
+ // Stop the old timer and start an updated one.
+ if (upload_timer_.IsRunning())
+ upload_timer_.Stop();
+ upload_timer_.Start(
+ FROM_HERE, report.upload_at - now, this,
+ &FeedbackUploader::UpdateUploadTimer);
+ }
+}
+
+void FeedbackUploader::RetryReport(scoped_ptr<std::string> data) {
+ reports_queue_.push(
+ FeedbackReport(base::Time::Now() + retry_delay_, data.Pass()));
+ UpdateUploadTimer();
+}
+
+void FeedbackUploader::setup_for_test(
+ const ReportDataCallback& dispatch_callback,
+ const base::TimeDelta& retry_delay) {
+ dispatch_callback_ = dispatch_callback;
+ retry_delay_ = retry_delay;
+}
+
+} // namespace feedback
diff --git a/chrome/browser/feedback/feedback_uploader.h b/chrome/browser/feedback/feedback_uploader.h
new file mode 100644
index 0000000..5c31047
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader.h
@@ -0,0 +1,76 @@
+// Copyright 2013 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.
+
+#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_H_
+#define CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_H_
+
+#include <queue>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/feedback/feedback_uploader_delegate.h"
+#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace feedback {
+
+struct FeedbackReport;
+
+// FeedbackUploader is used to add a feedback report to the queue of reports
+// being uploaded. In case uploading a report fails, it is written to disk and
+// tried again when it's turn comes up next in the queue.
+class FeedbackUploader : public BrowserContextKeyedService,
+ public base::SupportsWeakPtr<FeedbackUploader> {
+ public:
+ explicit FeedbackUploader(content::BrowserContext* context);
+ virtual ~FeedbackUploader();
+
+ void QueueReport(scoped_ptr<std::string> data);
+
+ private:
+ friend class FeedbackUploaderTest;
+ struct ReportsUploadTimeComparator {
+ bool operator()(const FeedbackReport& a, const FeedbackReport& b) const;
+ };
+
+ // Dispatches the report to be uploaded.
+ void DispatchReport(scoped_ptr<std::string> data);
+
+ // Update our timer for uploading the next report.
+ void UpdateUploadTimer();
+
+ // Requeue this report with a delay.
+ void RetryReport(scoped_ptr<std::string> data);
+
+ void setup_for_test(const ReportDataCallback& dispatch_callback,
+ const base::TimeDelta& retry_delay);
+
+ // Browser context this uploader was created for.
+ content::BrowserContext* context_;
+ // Timer to upload the next report at.
+ base::OneShotTimer<FeedbackUploader> upload_timer_;
+ // Priority queue of reports prioritized by the time the report is supposed
+ // to be uploaded at.
+ std::priority_queue<FeedbackReport,
+ std::vector<FeedbackReport>,
+ ReportsUploadTimeComparator> reports_queue_;
+
+ std::vector<FeedbackReport> loaded_reports_;
+
+ ReportDataCallback dispatch_callback_;
+ base::TimeDelta retry_delay_;
+
+ DISALLOW_COPY_AND_ASSIGN(FeedbackUploader);
+};
+
+} // namespace feedback
+
+#endif // CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_H_
diff --git a/chrome/browser/feedback/feedback_uploader_delegate.cc b/chrome/browser/feedback/feedback_uploader_delegate.cc
new file mode 100644
index 0000000..993d590
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader_delegate.cc
@@ -0,0 +1,65 @@
+// Copyright 2013 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/feedback/feedback_uploader_delegate.h"
+
+#include <sstream>
+
+#include "base/logging.h"
+#include "net/url_request/url_fetcher.h"
+#include "url/gurl.h"
+
+namespace feedback {
+namespace {
+
+const int kHttpPostSuccessNoContent = 204;
+const int kHttpPostFailNoConnection = -1;
+const int kHttpPostFailClientError = 400;
+const int kHttpPostFailServerError = 500;
+
+} // namespace
+
+FeedbackUploaderDelegate::FeedbackUploaderDelegate(
+ scoped_ptr<std::string> post_body,
+ const base::Closure& success_callback,
+ const ReportDataCallback& error_callback)
+ : post_body_(post_body.Pass()),
+ success_callback_(success_callback),
+ error_callback_(error_callback) {
+}
+
+FeedbackUploaderDelegate::~FeedbackUploaderDelegate() {}
+
+void FeedbackUploaderDelegate::OnURLFetchComplete(
+ const net::URLFetcher* source) {
+ scoped_ptr<const net::URLFetcher> source_scoper(source);
+
+ std::stringstream error_stream;
+ int response_code = source->GetResponseCode();
+ if (response_code == kHttpPostSuccessNoContent) {
+ error_stream << "Success";
+ success_callback_.Run();
+ } else {
+ // Process the error for debug output
+ if (response_code == kHttpPostFailNoConnection) {
+ error_stream << "No connection to server.";
+ } else if ((response_code > kHttpPostFailClientError) &&
+ (response_code < kHttpPostFailServerError)) {
+ error_stream << "Client error: HTTP response code " << response_code;
+ } else if (response_code > kHttpPostFailServerError) {
+ error_stream << "Server error: HTTP response code " << response_code;
+ } else {
+ error_stream << "Unknown error: HTTP response code " << response_code;
+ }
+ error_callback_.Run(post_body_.Pass());
+ }
+
+ LOG(WARNING) << "FEEDBACK: Submission to feedback server ("
+ << source->GetURL() << ") status: " << error_stream.str();
+
+ // This instance won't be used for anything else, delete us.
+ delete this;
+}
+
+} // namespace feedback
diff --git a/chrome/browser/feedback/feedback_uploader_delegate.h b/chrome/browser/feedback/feedback_uploader_delegate.h
new file mode 100644
index 0000000..5da18dd
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader_delegate.h
@@ -0,0 +1,42 @@
+// Copyright 2013 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.
+
+#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_DELEGATE_H_
+#define CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_DELEGATE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_fetcher_delegate.h"
+
+namespace feedback {
+
+typedef base::Callback<void(scoped_ptr<std::string>)> ReportDataCallback;
+
+// FeedbackUploaderDelegate is a simple http uploader for a feedback report. On
+// succes or failure, it deletes itself, but on failure it also notifies the
+// error callback specified when constructing the class instance.
+class FeedbackUploaderDelegate : public net::URLFetcherDelegate {
+ public:
+ FeedbackUploaderDelegate(scoped_ptr<std::string> post_body,
+ const base::Closure& success_callback,
+ const ReportDataCallback& error_callback);
+ virtual ~FeedbackUploaderDelegate();
+
+ private:
+ // Overridden from net::URLFetcherDelegate.
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+ scoped_ptr<std::string> post_body_;
+ base::Closure success_callback_;
+ ReportDataCallback error_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(FeedbackUploaderDelegate);
+};
+
+} // namespace feedback
+
+#endif // CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_DELEGATE_H_
diff --git a/chrome/browser/feedback/feedback_uploader_factory.cc b/chrome/browser/feedback/feedback_uploader_factory.cc
new file mode 100644
index 0000000..02dbc35
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader_factory.cc
@@ -0,0 +1,37 @@
+// Copyright 2013 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/feedback/feedback_uploader_factory.h"
+
+#include "base/memory/singleton.h"
+#include "chrome/browser/feedback/feedback_uploader.h"
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+
+namespace feedback {
+
+// static
+FeedbackUploaderFactory* FeedbackUploaderFactory::GetInstance() {
+ return Singleton<FeedbackUploaderFactory>::get();
+}
+
+// static
+FeedbackUploader* FeedbackUploaderFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<FeedbackUploader*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+FeedbackUploaderFactory::FeedbackUploaderFactory()
+ : BrowserContextKeyedServiceFactory(
+ "feedback::FeedbackUploader",
+ BrowserContextDependencyManager::GetInstance()) {}
+
+FeedbackUploaderFactory::~FeedbackUploaderFactory() {}
+
+BrowserContextKeyedService* FeedbackUploaderFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new FeedbackUploader(context);
+}
+
+} // namespace feedback
diff --git a/chrome/browser/feedback/feedback_uploader_factory.h b/chrome/browser/feedback/feedback_uploader_factory.h
new file mode 100644
index 0000000..ce80a5b
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2013 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.
+
+#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_FACTORY_H_
+#define CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_FACTORY_H_
+
+#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
+
+template<typename T> struct DefaultSingletonTraits;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace feedback {
+
+class FeedbackUploader;
+
+// Singleton that owns the FeedbackUploaders and associates them with profiles;
+class FeedbackUploaderFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ // Returns singleton instance of FeedbackUploaderFactory.
+ static FeedbackUploaderFactory* GetInstance();
+
+ // Returns the Feedback Uploader associated with |context|.
+ static FeedbackUploader* GetForBrowserContext(
+ content::BrowserContext* context);
+
+ private:
+ friend struct DefaultSingletonTraits<FeedbackUploaderFactory>;
+
+ FeedbackUploaderFactory();
+ virtual ~FeedbackUploaderFactory();
+
+ // BrowserContextKeyedServiceFactory overrides:
+ virtual BrowserContextKeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const OVERRIDE;
+
+ DISALLOW_COPY_AND_ASSIGN(FeedbackUploaderFactory);
+};
+
+} // namespace feedback
+
+#endif // CHROME_BROWSER_FEEDBACK_FEEDBACK_UPLOADER_FACTORY_H_
diff --git a/chrome/browser/feedback/feedback_uploader_unittest.cc b/chrome/browser/feedback/feedback_uploader_unittest.cc
new file mode 100644
index 0000000..8ba73e2
--- /dev/null
+++ b/chrome/browser/feedback/feedback_uploader_unittest.cc
@@ -0,0 +1,131 @@
+// Copyright (c) 2012 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/feedback/feedback_uploader.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "chrome/browser/feedback/feedback_uploader_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kReportOne[] = "one";
+const char kReportTwo[] = "two";
+const char kReportThree[] = "three";
+const char kReportFour[] = "four";
+const char kReportFive[] = "five";
+
+const base::TimeDelta kRetryDelayForTest =
+ base::TimeDelta::FromMilliseconds(100);
+
+BrowserContextKeyedService* CreateFeedbackUploaderService(
+ content::BrowserContext* context) {
+ return new feedback::FeedbackUploader(Profile::FromBrowserContext(context));
+}
+
+} // namespace
+
+namespace feedback {
+
+class FeedbackUploaderTest : public testing::Test {
+ protected:
+ FeedbackUploaderTest()
+ : ui_thread_(content::BrowserThread::UI, &message_loop_),
+ profile_(new TestingProfile()),
+ expected_reports_(0) {
+ FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
+ profile_.get(), &CreateFeedbackUploaderService);
+
+ uploader_ = FeedbackUploaderFactory::GetForBrowserContext(profile_.get());
+ uploader_->setup_for_test(
+ base::Bind(&FeedbackUploaderTest::MockDispatchReport,
+ base::Unretained(this)),
+ kRetryDelayForTest);
+ }
+
+ virtual ~FeedbackUploaderTest() {
+ FeedbackUploaderFactory::GetInstance()->SetTestingFactory(
+ profile_.get(), NULL);
+ }
+
+ void QueueReport(const std::string& data) {
+ uploader_->QueueReport(make_scoped_ptr(new std::string(data)));
+ }
+
+ void ReportFailure(const std::string& data) {
+ uploader_->RetryReport(make_scoped_ptr(new std::string(data)));
+ }
+
+ void MockDispatchReport(scoped_ptr<std::string> report_data) {
+ dispatched_reports_.push_back(*report_data.get());
+
+ // Dispatch will always update the timer, whether successful or not,
+ // simulate the same behavior.
+ uploader_->UpdateUploadTimer();
+
+ if (dispatched_reports_.size() >= expected_reports_) {
+ if (run_loop_.get())
+ run_loop_->Quit();
+ }
+ }
+
+ void RunMessageLoop() {
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ }
+
+ base::MessageLoop message_loop_;
+ scoped_ptr<base::RunLoop> run_loop_;
+ content::TestBrowserThread ui_thread_;
+ scoped_ptr<TestingProfile> profile_;
+
+ FeedbackUploader* uploader_;
+
+ std::vector<std::string> dispatched_reports_;
+ size_t expected_reports_;
+};
+
+TEST_F(FeedbackUploaderTest, QueueMultiple) {
+ dispatched_reports_.clear();
+ QueueReport(kReportOne);
+ QueueReport(kReportTwo);
+ QueueReport(kReportThree);
+ QueueReport(kReportFour);
+
+ EXPECT_EQ(dispatched_reports_.size(), 4u);
+ EXPECT_EQ(dispatched_reports_[0], kReportOne);
+ EXPECT_EQ(dispatched_reports_[1], kReportTwo);
+ EXPECT_EQ(dispatched_reports_[2], kReportThree);
+ EXPECT_EQ(dispatched_reports_[3], kReportFour);
+}
+
+TEST_F(FeedbackUploaderTest, QueueMultipleWithFailures) {
+ dispatched_reports_.clear();
+ QueueReport(kReportOne);
+ QueueReport(kReportTwo);
+ QueueReport(kReportThree);
+ QueueReport(kReportFour);
+
+ ReportFailure(kReportThree);
+ ReportFailure(kReportTwo);
+ QueueReport(kReportFive);
+
+ expected_reports_ = 7;
+ RunMessageLoop();
+
+ EXPECT_EQ(dispatched_reports_.size(), 7u);
+ EXPECT_EQ(dispatched_reports_[0], kReportOne);
+ EXPECT_EQ(dispatched_reports_[1], kReportTwo);
+ EXPECT_EQ(dispatched_reports_[2], kReportThree);
+ EXPECT_EQ(dispatched_reports_[3], kReportFour);
+ EXPECT_EQ(dispatched_reports_[4], kReportFive);
+ EXPECT_EQ(dispatched_reports_[5], kReportThree);
+ EXPECT_EQ(dispatched_reports_[6], kReportTwo);
+}
+
+} // namespace feedback
diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc
index b6926db..94e3c53 100644
--- a/chrome/browser/feedback/feedback_util.cc
+++ b/chrome/browser/feedback/feedback_util.cc
@@ -21,6 +21,8 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/feedback_private/feedback_private_api.h"
#include "chrome/browser/feedback/feedback_data.h"
+#include "chrome/browser/feedback/feedback_uploader.h"
+#include "chrome/browser/feedback/feedback_uploader_factory.h"
#include "chrome/browser/metrics/variations/variations_http_header_provider.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -51,8 +53,6 @@
namespace {
-void DispatchFeedback(Profile* profile, std::string* post_body, int64 delay);
-
GURL GetTargetTabUrl(int session_id, int index) {
Browser* browser = chrome::FindBrowserWithID(session_id);
// Sanity checks.
@@ -69,22 +69,7 @@ GURL GetTargetTabUrl(int session_id, int index) {
return GURL();
}
-// URL to post bug reports to.
-const char kFeedbackPostUrl[] =
- "https://www.google.com/tools/feedback/chrome/__submit";
-
-const char kProtBufMimeType[] = "application/x-protobuf";
const char kPngMimeType[] = "image/png";
-
-const int kHttpPostSuccessNoContent = 204;
-const int kHttpPostFailNoConnection = -1;
-const int kHttpPostFailClientError = 400;
-const int kHttpPostFailServerError = 500;
-
-const int64 kInitialRetryDelay = 900000; // 15 minutes
-const int64 kRetryDelayIncreaseFactor = 2;
-const int64 kRetryDelayLimit = 14400000; // 4 hours
-
const char kArbitraryMimeType[] = "application/octet-stream";
const char kHistogramsAttachmentName[] = "histograms.zip";
const char kLogsAttachmentName[] = "system_logs.zip";
@@ -95,111 +80,6 @@ const int kChromeOSProductId = 208;
const int kChromeBrowserProductId = 237;
#endif
-// Simple net::URLFetcherDelegate to clean up URLFetcher on completion.
-class PostCleanup : public net::URLFetcherDelegate {
- public:
- PostCleanup(Profile* profile,
- std::string* post_body,
- int64 previous_delay) : profile_(profile),
- post_body_(post_body),
- previous_delay_(previous_delay) { }
- // Overridden from net::URLFetcherDelegate.
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
- protected:
- virtual ~PostCleanup() {}
-
- private:
- Profile* profile_;
- std::string* post_body_;
- int64 previous_delay_;
-
- DISALLOW_COPY_AND_ASSIGN(PostCleanup);
-};
-
-// Don't use the data parameter, instead use the pointer we pass into every
-// post cleanup object - that pointer will be deleted and deleted only on a
-// successful post to the feedback server.
-void PostCleanup::OnURLFetchComplete(
- const net::URLFetcher* source) {
- std::stringstream error_stream;
- int response_code = source->GetResponseCode();
- if (response_code == kHttpPostSuccessNoContent) {
- // We've sent our report, delete the report data
- delete post_body_;
-
- error_stream << "Success";
- } else {
- // Uh oh, feedback failed, send it off to retry
- if (previous_delay_) {
- if (previous_delay_ < kRetryDelayLimit)
- previous_delay_ *= kRetryDelayIncreaseFactor;
- } else {
- previous_delay_ = kInitialRetryDelay;
- }
- DispatchFeedback(profile_, post_body_, previous_delay_);
-
- // Process the error for debug output
- if (response_code == kHttpPostFailNoConnection) {
- error_stream << "No connection to server.";
- } else if ((response_code > kHttpPostFailClientError) &&
- (response_code < kHttpPostFailServerError)) {
- error_stream << "Client error: HTTP response code " << response_code;
- } else if (response_code > kHttpPostFailServerError) {
- error_stream << "Server error: HTTP response code " << response_code;
- } else {
- error_stream << "Unknown error: HTTP response code " << response_code;
- }
- }
-
- LOG(WARNING) << "FEEDBACK: Submission to feedback server (" <<
- source->GetURL() << ") status: " << error_stream.str();
-
- // Delete the URLFetcher.
- delete source;
- // And then delete ourselves.
- delete this;
-}
-
-void SendFeedback(Profile* profile,
- std::string* post_body,
- int64 previous_delay) {
- DCHECK(post_body);
-
- GURL post_url;
- if (CommandLine::ForCurrentProcess()->
- HasSwitch(switches::kFeedbackServer))
- post_url = GURL(CommandLine::ForCurrentProcess()->
- GetSwitchValueASCII(switches::kFeedbackServer));
- else
- post_url = GURL(kFeedbackPostUrl);
-
- net::URLFetcher* fetcher = net::URLFetcher::Create(
- post_url, net::URLFetcher::POST,
- new PostCleanup(profile, post_body, previous_delay));
- fetcher->SetRequestContext(profile->GetRequestContext());
- fetcher->SetLoadFlags(
- net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES);
-
- net::HttpRequestHeaders headers;
- chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
- fetcher->GetOriginalURL(), profile->IsOffTheRecord(), false, &headers);
- fetcher->SetExtraRequestHeaders(headers.ToString());
-
- fetcher->SetUploadData(std::string(kProtBufMimeType), *post_body);
- fetcher->Start();
-}
-
-void DispatchFeedback(Profile* profile, std::string* post_body, int64 delay) {
- DCHECK(post_body);
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&SendFeedback, profile, post_body, delay),
- base::TimeDelta::FromMilliseconds(delay));
-}
-
-
void AddFeedbackData(userfeedback::ExtensionSubmit* feedback_data,
const std::string& key, const std::string& value) {
// Don't bother with empty keys or values
@@ -359,10 +239,12 @@ void SendReport(scoped_refptr<FeedbackData> data) {
// This pointer will eventually get deleted by the PostCleanup class, after
// we've either managed to successfully upload the report or died trying.
- std::string* post_body = new std::string;
- feedback_data.SerializeToString(post_body);
+ scoped_ptr<std::string> post_body(new std::string);
+ feedback_data.SerializeToString(post_body.get());
- DispatchFeedback(data->profile(), post_body, 0);
+ feedback::FeedbackUploader *uploader =
+ feedback::FeedbackUploaderFactory::GetForBrowserContext(data->profile());
+ uploader->QueueReport(post_body.Pass());
}
bool ZipString(const base::FilePath& filename,