diff options
author | rkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-24 22:55:08 +0000 |
---|---|---|
committer | rkc@chromium.org <rkc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-24 22:55:08 +0000 |
commit | 85328dd3f2c23cc3f54c4c792abda31e2db9d270 (patch) | |
tree | 0b100754e0ab19dd484818e0c355005699d87cd8 | |
parent | cf869b1161c5b2b9f751c759b273613e2c8477d4 (diff) | |
download | chromium_src-85328dd3f2c23cc3f54c4c792abda31e2db9d270.zip chromium_src-85328dd3f2c23cc3f54c4c792abda31e2db9d270.tar.gz chromium_src-85328dd3f2c23cc3f54c4c792abda31e2db9d270.tar.bz2 |
Cache feedback reports to disk in case of send failure.
R=zork@chromium.org
BUG=249853
Review URL: https://codereview.chromium.org/141433011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@246992 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 5 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_profile_observer.cc | 60 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_profile_observer.h | 50 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_report.cc | 91 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_report.h | 63 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_uploader.cc | 58 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_uploader.h | 21 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_uploader_delegate.cc | 6 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_uploader_delegate.h | 7 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_uploader_unittest.cc | 8 | ||||
-rw-r--r-- | chrome/browser/feedback/feedback_util.cc | 6 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 4 |
12 files changed, 317 insertions, 62 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 77205a8..97df1af 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -56,6 +56,7 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/startup_helper.h" +#include "chrome/browser/feedback/feedback_profile_observer.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/google/google_search_counter.h" @@ -1027,6 +1028,10 @@ void ChromeBrowserMainParts::PreMainMessageLoopRun() { void ChromeBrowserMainParts::PreProfileInit() { TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreProfileInit"); + // Initialize the feedback uploader so it can setup notifications for profile + // creation. + feedback::FeedbackProfileObserver::Initialize(); + for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) chrome_extra_parts_[i]->PreProfileInit(); diff --git a/chrome/browser/feedback/feedback_profile_observer.cc b/chrome/browser/feedback/feedback_profile_observer.cc new file mode 100644 index 0000000..0ec0b73 --- /dev/null +++ b/chrome/browser/feedback/feedback_profile_observer.cc @@ -0,0 +1,60 @@ +// 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 "chrome/browser/feedback/feedback_profile_observer.h" + +#include "base/callback.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/feedback/feedback_report.h" +#include "chrome/browser/feedback/feedback_uploader.h" +#include "chrome/browser/feedback/feedback_uploader_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_service.h" + +using content::BrowserThread; + +static base::LazyInstance<feedback::FeedbackProfileObserver>::Leaky + g_feedback_profile_observer = LAZY_INSTANCE_INITIALIZER; + +namespace feedback { + +// static +void FeedbackProfileObserver::Initialize() { + g_feedback_profile_observer.Get(); +} + +FeedbackProfileObserver::FeedbackProfileObserver() { + prefs_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED, + content::NotificationService::AllSources()); +} + +FeedbackProfileObserver::~FeedbackProfileObserver() { + prefs_registrar_.RemoveAll(); +} + +void FeedbackProfileObserver::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CREATED, type); + + Profile* profile = content::Source<Profile>(source).ptr(); + if (!profile->IsOffTheRecord()) + QueueUnsentReports(profile); +} + +void FeedbackProfileObserver::QueueUnsentReports( + content::BrowserContext* context) { + feedback::FeedbackUploader* uploader = + feedback::FeedbackUploaderFactory::GetForBrowserContext(context); + BrowserThread::PostBlockingPoolTask(FROM_HERE, + base::Bind( + &FeedbackReport::LoadReportsAndQueue, context, base::Bind( + &FeedbackUploader::QueueReport, uploader->AsWeakPtr()))); +} + +} // namespace feedback diff --git a/chrome/browser/feedback/feedback_profile_observer.h b/chrome/browser/feedback/feedback_profile_observer.h new file mode 100644 index 0000000..4a48c99 --- /dev/null +++ b/chrome/browser/feedback/feedback_profile_observer.h @@ -0,0 +1,50 @@ +// 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. + +#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_PROFILE_OBSERVER_H_ +#define CHROME_BROWSER_FEEDBACK_FEEDBACK_PROFILE_OBSERVER_H_ + +#include "base/basictypes.h" +#include "base/lazy_instance.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +namespace content { +class BrowserContext; +} + +namespace feedback { + +// FeedbackProfileObserver waits on profile creation notifications to check +// if the profile has any pending feedback reports to upload. If it does, it +// queues those reports for upload. +class FeedbackProfileObserver : public content::NotificationObserver { + public: + static void Initialize(); + + private: + friend struct base::DefaultLazyInstanceTraits<FeedbackProfileObserver>; + + FeedbackProfileObserver(); + virtual ~FeedbackProfileObserver(); + + // content::NotificationObserver override + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + // Loads any unsent reports from disk and queues them to be uploaded in + // the given browser context. + void QueueUnsentReports(content::BrowserContext* context); + + // Used to track creation of profiles so we can load any unsent reports + // for that profile. + content::NotificationRegistrar prefs_registrar_; + + DISALLOW_COPY_AND_ASSIGN(FeedbackProfileObserver); +}; + +} // namespace feedback + +#endif // CHROME_BROWSER_FEEDBACK_FEEDBACK_PROFILE_OBSERVER_H_ diff --git a/chrome/browser/feedback/feedback_report.cc b/chrome/browser/feedback/feedback_report.cc new file mode 100644 index 0000000..bfea487 --- /dev/null +++ b/chrome/browser/feedback/feedback_report.cc @@ -0,0 +1,91 @@ +// 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 "chrome/browser/feedback/feedback_report.h" + +#include "base/file_util.h" +#include "base/files/file_enumerator.h" +#include "base/files/important_file_writer.h" +#include "base/guid.h" +#include "base/strings/string_number_conversions.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "net/base/directory_lister.h" + +using content::BrowserThread; + +namespace { + +const base::FilePath::CharType kFeedbackReportPath[] = + FILE_PATH_LITERAL("Feedback Reports"); +const base::FilePath::CharType kFeedbackReportFilenameWildcard[] = + FILE_PATH_LITERAL("Feedback Report.*"); + +const char kFeedbackReportFilenamePrefix[] = "Feedback Report."; + +base::FilePath GetFeedbackReportsPath(content::BrowserContext* context) { + return context->GetPath().Append(kFeedbackReportPath); +} + +} // namespace + +namespace feedback { + +FeedbackReport::FeedbackReport(content::BrowserContext* context, + const base::Time& upload_at, + const std::string& data) + : context_(context), + upload_at_(upload_at), + data_(data) { + base::FilePath reports_path = GetFeedbackReportsPath(context); + if (reports_path.empty()) + return; + file_ = reports_path.AppendASCII( + kFeedbackReportFilenamePrefix + base::GenerateGUID()); + BrowserThread::PostBlockingPoolTask(FROM_HERE, base::Bind( + &FeedbackReport::WriteReportOnBlockingPool, this)); +} + +FeedbackReport::~FeedbackReport() {} + +void FeedbackReport::DeleteReportOnDisk() { + BrowserThread::PostBlockingPoolTask(FROM_HERE, base::Bind( + base::IgnoreResult(&base::DeleteFile), file_, false)); + file_.clear(); +} + +void FeedbackReport::WriteReportOnBlockingPool() { + base::FilePath reports_path = GetFeedbackReportsPath(context_); + if (!base::DirectoryExists(reports_path)) { + base::File::Error error; + if (!base::CreateDirectoryAndGetError(reports_path, &error)) + return; + } + if (!file_.empty()) + base::ImportantFileWriter::WriteFileAtomically(file_, data_); +} + +// static +void FeedbackReport::LoadReportsAndQueue( + content::BrowserContext* context, QueueCallback callback) { + base::FilePath reports_path = GetFeedbackReportsPath(context); + if (reports_path.empty()) + return; + + base::FileEnumerator enumerator(reports_path, + false, + base::FileEnumerator::FILES, + kFeedbackReportFilenameWildcard); + for (base::FilePath name = enumerator.Next(); + !name.empty(); + name = enumerator.Next()) { + std::string data; + if (ReadFileToString(name, &data)) + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, base::Bind(callback, data)); + base::DeleteFile(name, false); + } +} + +} // namespace feedback diff --git a/chrome/browser/feedback/feedback_report.h b/chrome/browser/feedback/feedback_report.h new file mode 100644 index 0000000..3c9e4e26 --- /dev/null +++ b/chrome/browser/feedback/feedback_report.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_REPORT_H_ +#define CHROME_BROWSER_FEEDBACK_FEEDBACK_REPORT_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/time/time.h" + +namespace content { +class BrowserContext; +} + +namespace feedback { + +typedef base::Callback<void(const std::string&)> QueueCallback; + +// This class holds a feedback report. Once a report is created, a disk backup +// for it is created automatically. This backup is deleted once this object +// dies. +class FeedbackReport : public base::RefCountedThreadSafe<FeedbackReport> { + public: + FeedbackReport(content::BrowserContext* context, + const base::Time& upload_at, + const std::string& data); + + // Stops the disk write of the report and deletes the report file if already + // written. + void DeleteReportOnDisk(); + + base::Time upload_at() { return upload_at_; } + const std::string& data() { return data_; } + + // Loads the reports still on disk and queues then using the given callback. + // This call blocks on the file reads. + static void LoadReportsAndQueue(content::BrowserContext* context, + QueueCallback callback); + + private: + friend class base::RefCountedThreadSafe<FeedbackReport>; + virtual ~FeedbackReport(); + + void WriteReportOnBlockingPool(); + + // Name of the file corresponding to this report. + base::FilePath file_; + + content::BrowserContext* context_; + base::Time upload_at_; // Upload this report at or after this time. + std::string data_; + + DISALLOW_COPY_AND_ASSIGN(FeedbackReport); +}; + +} // namespace feedback + +#endif // CHROME_BROWSER_FEEDBACK_FEEDBACK_REPORT_H_ diff --git a/chrome/browser/feedback/feedback_uploader.cc b/chrome/browser/feedback/feedback_uploader.cc index 36d5620..75b3a6a 100644 --- a/chrome/browser/feedback/feedback_uploader.cc +++ b/chrome/browser/feedback/feedback_uploader.cc @@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/task_runner_util.h" #include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/feedback/feedback_report.h" #include "chrome/common/chrome_switches.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -29,28 +30,9 @@ const int64 kRetryDelayMinutes = 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; + FeedbackReport* a, FeedbackReport* b) const { + return a->upload_at() > b->upload_at(); } FeedbackUploader::FeedbackUploader(content::BrowserContext* context) @@ -61,15 +43,15 @@ FeedbackUploader::FeedbackUploader(content::BrowserContext* context) AsWeakPtr()); } -FeedbackUploader::~FeedbackUploader() { -} +FeedbackUploader::~FeedbackUploader() {} -void FeedbackUploader::QueueReport(scoped_ptr<std::string> data) { - reports_queue_.push(FeedbackReport(base::Time::Now(), data.Pass())); +void FeedbackUploader::QueueReport(const std::string& data) { + reports_queue_.push( + new FeedbackReport(context_, base::Time::Now(), data)); UpdateUploadTimer(); } -void FeedbackUploader::DispatchReport(scoped_ptr<std::string> data) { +void FeedbackUploader::DispatchReport(const std::string& data) { GURL post_url; if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kFeedbackServer)) post_url = GURL(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( @@ -77,17 +59,14 @@ void FeedbackUploader::DispatchReport(scoped_ptr<std::string> data) { 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(), + data, base::Bind(&FeedbackUploader::UpdateUploadTimer, AsWeakPtr()), base::Bind(&FeedbackUploader::RetryReport, AsWeakPtr()))); - fetcher->SetUploadData(std::string(kProtBufMimeType), *data_ptr); + fetcher->SetUploadData(std::string(kProtBufMimeType), data); fetcher->SetRequestContext(context_->GetRequestContext()); fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES); @@ -98,25 +77,26 @@ void FeedbackUploader::UpdateUploadTimer() { if (reports_queue_.empty()) return; - const FeedbackReport& report = reports_queue_.top(); + scoped_refptr<FeedbackReport> report = reports_queue_.top(); base::Time now = base::Time::Now(); - if (report.upload_at <= now) { - scoped_ptr<std::string> data = report.data.Pass(); + if (report->upload_at() <= now) { reports_queue_.pop(); - dispatch_callback_.Run(data.Pass()); + dispatch_callback_.Run(report->data()); + report->DeleteReportOnDisk(); } 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, + 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())); +void FeedbackUploader::RetryReport(const std::string& data) { + reports_queue_.push(new FeedbackReport(context_, + base::Time::Now() + retry_delay_, + data)); UpdateUploadTimer(); } diff --git a/chrome/browser/feedback/feedback_uploader.h b/chrome/browser/feedback/feedback_uploader.h index 5c31047..9ddf3a0 100644 --- a/chrome/browser/feedback/feedback_uploader.h +++ b/chrome/browser/feedback/feedback_uploader.h @@ -22,7 +22,7 @@ class BrowserContext; namespace feedback { -struct FeedbackReport; +class 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 @@ -33,22 +33,27 @@ class FeedbackUploader : public BrowserContextKeyedService, explicit FeedbackUploader(content::BrowserContext* context); virtual ~FeedbackUploader(); - void QueueReport(scoped_ptr<std::string> data); + // Queues a report for uploading. + void QueueReport(const std::string& data); private: friend class FeedbackUploaderTest; struct ReportsUploadTimeComparator { - bool operator()(const FeedbackReport& a, const FeedbackReport& b) const; + bool operator()(FeedbackReport* a, FeedbackReport* b) const; }; // Dispatches the report to be uploaded. - void DispatchReport(scoped_ptr<std::string> data); + void DispatchReport(const std::string& data); + + // Loads any unsent reports from disk and queues them to be uploaded in + // the given browser context. + void QueueUnsentReports(content::BrowserContext* context); // Update our timer for uploading the next report. void UpdateUploadTimer(); // Requeue this report with a delay. - void RetryReport(scoped_ptr<std::string> data); + void RetryReport(const std::string& data); void setup_for_test(const ReportDataCallback& dispatch_callback, const base::TimeDelta& retry_delay); @@ -59,12 +64,10 @@ class FeedbackUploader : public BrowserContextKeyedService, 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>, + std::priority_queue<scoped_refptr<FeedbackReport>, + std::vector<scoped_refptr<FeedbackReport> >, ReportsUploadTimeComparator> reports_queue_; - std::vector<FeedbackReport> loaded_reports_; - ReportDataCallback dispatch_callback_; base::TimeDelta retry_delay_; diff --git a/chrome/browser/feedback/feedback_uploader_delegate.cc b/chrome/browser/feedback/feedback_uploader_delegate.cc index 993d590..28256dd 100644 --- a/chrome/browser/feedback/feedback_uploader_delegate.cc +++ b/chrome/browser/feedback/feedback_uploader_delegate.cc @@ -21,10 +21,10 @@ const int kHttpPostFailServerError = 500; } // namespace FeedbackUploaderDelegate::FeedbackUploaderDelegate( - scoped_ptr<std::string> post_body, + const std::string& post_body, const base::Closure& success_callback, const ReportDataCallback& error_callback) - : post_body_(post_body.Pass()), + : post_body_(post_body), success_callback_(success_callback), error_callback_(error_callback) { } @@ -52,7 +52,7 @@ void FeedbackUploaderDelegate::OnURLFetchComplete( } else { error_stream << "Unknown error: HTTP response code " << response_code; } - error_callback_.Run(post_body_.Pass()); + error_callback_.Run(post_body_); } LOG(WARNING) << "FEEDBACK: Submission to feedback server (" diff --git a/chrome/browser/feedback/feedback_uploader_delegate.h b/chrome/browser/feedback/feedback_uploader_delegate.h index 5da18dd..b500104 100644 --- a/chrome/browser/feedback/feedback_uploader_delegate.h +++ b/chrome/browser/feedback/feedback_uploader_delegate.h @@ -9,19 +9,18 @@ #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; +typedef base::Callback<void(const 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, + FeedbackUploaderDelegate(const std::string& post_body, const base::Closure& success_callback, const ReportDataCallback& error_callback); virtual ~FeedbackUploaderDelegate(); @@ -30,7 +29,7 @@ class FeedbackUploaderDelegate : public net::URLFetcherDelegate { // Overridden from net::URLFetcherDelegate. virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; - scoped_ptr<std::string> post_body_; + std::string post_body_; base::Closure success_callback_; ReportDataCallback error_callback_; diff --git a/chrome/browser/feedback/feedback_uploader_unittest.cc b/chrome/browser/feedback/feedback_uploader_unittest.cc index 407a286..917e0b1 100644 --- a/chrome/browser/feedback/feedback_uploader_unittest.cc +++ b/chrome/browser/feedback/feedback_uploader_unittest.cc @@ -54,15 +54,15 @@ class FeedbackUploaderTest : public testing::Test { } void QueueReport(const std::string& data) { - uploader_->QueueReport(make_scoped_ptr(new std::string(data))); + uploader_->QueueReport(data); } void ReportFailure(const std::string& data) { - uploader_->RetryReport(make_scoped_ptr(new std::string(data))); + uploader_->RetryReport(data); } - void MockDispatchReport(scoped_ptr<std::string> report_data) { - dispatched_reports_.push_back(*report_data.get()); + void MockDispatchReport(const std::string& report_data) { + dispatched_reports_.push_back(report_data); // Dispatch will always update the timer, whether successful or not, // simulate the same behavior. diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc index 94e3c53..f15a4bf 100644 --- a/chrome/browser/feedback/feedback_util.cc +++ b/chrome/browser/feedback/feedback_util.cc @@ -239,12 +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. - scoped_ptr<std::string> post_body(new std::string); - feedback_data.SerializeToString(post_body.get()); + std::string post_body; + feedback_data.SerializeToString(&post_body); feedback::FeedbackUploader *uploader = feedback::FeedbackUploaderFactory::GetForBrowserContext(data->profile()); - uploader->QueueReport(post_body.Pass()); + uploader->QueueReport(post_body); } bool ZipString(const base::FilePath& filename, diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 8d4e0d6..a9d6d30 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -359,6 +359,10 @@ 'browser/browsing_data/cookies_tree_model.h', 'browser/feedback/feedback_data.cc', 'browser/feedback/feedback_data.h', + 'browser/feedback/feedback_profile_observer.cc', + 'browser/feedback/feedback_profile_observer.h', + 'browser/feedback/feedback_report.cc', + 'browser/feedback/feedback_report.h', 'browser/feedback/feedback_util.cc', 'browser/feedback/feedback_util.h', 'browser/feedback/feedback_uploader.cc', |