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

Unified Diff: net/base/directory_lister.cc

Issue 786123002: Update from https://crrev.com/307330 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years 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 | « net/base/directory_lister.h ('k') | net/base/directory_lister_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/directory_lister.cc
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc
index 841f454c814bafa3865fc92c69304f75f2a36aa4..f746f9b2e476576098d8d5ea9c7400c4674c5ecb 100644
--- a/net/base/directory_lister.cc
+++ b/net/base/directory_lister.cc
@@ -5,12 +5,12 @@
#include "net/base/directory_lister.h"
#include <algorithm>
-#include <vector>
#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/i18n/file_util_icu.h"
+#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
@@ -73,22 +73,23 @@ void SortData(std::vector<DirectoryLister::DirectoryListerData>* data,
DirectoryLister::SortType sort_type) {
// Sort the results. See the TODO below (this sort should be removed and we
// should do it from JS).
- if (sort_type == DirectoryLister::DATE)
+ if (sort_type == DirectoryLister::DATE) {
std::sort(data->begin(), data->end(), CompareDate);
- else if (sort_type == DirectoryLister::FULL_PATH)
+ } else if (sort_type == DirectoryLister::FULL_PATH) {
std::sort(data->begin(), data->end(), CompareFullPath);
- else if (sort_type == DirectoryLister::ALPHA_DIRS_FIRST)
+ } else if (sort_type == DirectoryLister::ALPHA_DIRS_FIRST) {
std::sort(data->begin(), data->end(), CompareAlphaDirsFirst);
- else
+ } else {
DCHECK_EQ(DirectoryLister::NO_SORT, sort_type);
+ }
}
} // namespace
DirectoryLister::DirectoryLister(const base::FilePath& dir,
DirectoryListerDelegate* delegate)
- : core_(new Core(dir, false, ALPHA_DIRS_FIRST, this)),
- delegate_(delegate) {
+ : delegate_(delegate) {
+ core_ = new Core(dir, false, ALPHA_DIRS_FIRST, this);
DCHECK(delegate_);
DCHECK(!dir.value().empty());
}
@@ -97,8 +98,8 @@ DirectoryLister::DirectoryLister(const base::FilePath& dir,
bool recursive,
SortType sort,
DirectoryListerDelegate* delegate)
- : core_(new Core(dir, recursive, sort, this)),
- delegate_(delegate) {
+ : delegate_(delegate) {
+ core_ = new Core(dir, recursive, sort, this);
DCHECK(delegate_);
DCHECK(!dir.value().empty());
}
@@ -108,11 +109,14 @@ DirectoryLister::~DirectoryLister() {
}
bool DirectoryLister::Start() {
- return core_->Start();
+ return base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&Core::Start, core_),
+ true);
}
void DirectoryLister::Cancel() {
- return core_->Cancel();
+ core_->CancelOnOriginThread();
}
DirectoryLister::Core::Core(const base::FilePath& dir,
@@ -122,29 +126,32 @@ DirectoryLister::Core::Core(const base::FilePath& dir,
: dir_(dir),
recursive_(recursive),
sort_(sort),
- lister_(lister) {
+ origin_loop_(base::MessageLoopProxy::current()),
+ lister_(lister),
+ cancelled_(0) {
DCHECK(lister_);
}
DirectoryLister::Core::~Core() {}
-bool DirectoryLister::Core::Start() {
- origin_loop_ = base::MessageLoopProxy::current();
-
- return base::WorkerPool::PostTask(
- FROM_HERE, base::Bind(&Core::StartInternal, this), true);
-}
+void DirectoryLister::Core::CancelOnOriginThread() {
+ DCHECK(origin_loop_->BelongsToCurrentThread());
-void DirectoryLister::Core::Cancel() {
- lister_ = NULL;
+ base::subtle::NoBarrier_Store(&cancelled_, 1);
+ // Core must not call into |lister_| after cancellation, as the |lister_| may
+ // have been destroyed. Setting |lister_| to NULL ensures any such access will
+ // cause a crash.
+ lister_ = nullptr;
}
-void DirectoryLister::Core::StartInternal() {
+void DirectoryLister::Core::Start() {
+ scoped_ptr<DirectoryList> directory_list(new DirectoryList());
if (!base::DirectoryExists(dir_)) {
origin_loop_->PostTask(
FROM_HERE,
- base::Bind(&DirectoryLister::Core::OnDone, this, ERR_FILE_NOT_FOUND));
+ base::Bind(&Core::DoneOnOriginThread, this,
+ base::Passed(directory_list.Pass()), ERR_FILE_NOT_FOUND));
return;
}
@@ -155,12 +162,16 @@ void DirectoryLister::Core::StartInternal() {
base::FileEnumerator file_enum(dir_, recursive_, types);
base::FilePath path;
- std::vector<DirectoryListerData> file_data;
- while (lister_ && !(path = file_enum.Next()).empty()) {
+ while (!(path = file_enum.Next()).empty()) {
+ // Abort on cancellation. This is purely for performance reasons.
+ // Correctness guarantees are made by checks in DoneOnOriginThread.
+ if (IsCancelled())
+ return;
+
DirectoryListerData data;
data.info = file_enum.GetInfo();
data.path = path;
- file_data.push_back(data);
+ directory_list->push_back(data);
/* TODO(brettw) bug 24107: It would be nice to send incremental updates.
We gather them all so they can be sorted, but eventually the sorting
@@ -178,36 +189,40 @@ void DirectoryLister::Core::StartInternal() {
*/
}
- SortData(&file_data, sort_);
- origin_loop_->PostTask(
- FROM_HERE,
- base::Bind(&DirectoryLister::Core::SendData, this, file_data));
+ SortData(directory_list.get(), sort_);
origin_loop_->PostTask(
FROM_HERE,
- base::Bind(&DirectoryLister::Core::OnDone, this, OK));
+ base::Bind(&Core::DoneOnOriginThread, this,
+ base::Passed(directory_list.Pass()), OK));
}
-void DirectoryLister::Core::SendData(
- const std::vector<DirectoryLister::DirectoryListerData>& data) {
- DCHECK(origin_loop_->BelongsToCurrentThread());
- // We need to check for cancellation (indicated by NULL'ing of |lister_|)
- // which can happen during each callback.
- for (size_t i = 0; lister_ && i < data.size(); ++i)
- lister_->OnReceivedData(data[i]);
+bool DirectoryLister::Core::IsCancelled() const {
+ return !!base::subtle::NoBarrier_Load(&cancelled_);
}
-void DirectoryLister::Core::OnDone(int error) {
+void DirectoryLister::Core::DoneOnOriginThread(
+ scoped_ptr<DirectoryList> directory_list, int error) const {
DCHECK(origin_loop_->BelongsToCurrentThread());
- if (lister_)
- lister_->OnDone(error);
+
+ // Need to check if the operation was before first callback.
+ if (IsCancelled())
+ return;
+
+ for (const auto& lister_data : *directory_list) {
+ lister_->OnListFile(lister_data);
+ // Need to check if the operation was cancelled during the callback.
+ if (IsCancelled())
+ return;
+ }
+ lister_->OnListDone(error);
}
-void DirectoryLister::OnReceivedData(const DirectoryListerData& data) {
+void DirectoryLister::OnListFile(const DirectoryListerData& data) {
delegate_->OnListFile(data);
}
-void DirectoryLister::OnDone(int error) {
+void DirectoryLister::OnListDone(int error) {
delegate_->OnListDone(error);
}
« no previous file with comments | « net/base/directory_lister.h ('k') | net/base/directory_lister_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698