This source file includes following definitions.
- IsDotDot
 
- CompareAlphaDirsFirst
 
- CompareDate
 
- CompareFullPath
 
- SortData
 
- delegate_
 
- delegate_
 
- Start
 
- Cancel
 
- lister_
 
- Start
 
- Cancel
 
- StartInternal
 
- SendData
 
- OnDone
 
- OnReceivedData
 
- OnDone
 
#include "net/base/directory_lister.h"
#include <algorithm>
#include <vector>
#include "base/bind.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/i18n/file_util_icu.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/worker_pool.h"
#include "net/base/net_errors.h"
namespace net {
namespace {
bool IsDotDot(const base::FilePath& path) {
  return FILE_PATH_LITERAL("..") == path.BaseName().value();
}
bool CompareAlphaDirsFirst(const DirectoryLister::DirectoryListerData& a,
                           const DirectoryLister::DirectoryListerData& b) {
  
  if (IsDotDot(a.info.GetName()))
    return true;
  if (IsDotDot(b.info.GetName()))
    return false;
  
  bool a_is_directory = a.info.IsDirectory();
  bool b_is_directory = b.info.IsDirectory();
  if (a_is_directory != b_is_directory)
    return a_is_directory;
  return file_util::LocaleAwareCompareFilenames(a.info.GetName(),
                                                b.info.GetName());
}
bool CompareDate(const DirectoryLister::DirectoryListerData& a,
                 const DirectoryLister::DirectoryListerData& b) {
  
  if (IsDotDot(a.info.GetName()))
    return true;
  if (IsDotDot(b.info.GetName()))
    return false;
  
  bool a_is_directory = a.info.IsDirectory();
  bool b_is_directory = b.info.IsDirectory();
  if (a_is_directory != b_is_directory)
    return a_is_directory;
  return a.info.GetLastModifiedTime() > b.info.GetLastModifiedTime();
}
bool CompareFullPath(const DirectoryLister::DirectoryListerData& a,
                     const DirectoryLister::DirectoryListerData& b) {
  return file_util::LocaleAwareCompareFilenames(a.path, b.path);
}
void SortData(std::vector<DirectoryLister::DirectoryListerData>* data,
              DirectoryLister::SortType sort_type) {
  
  
  if (sort_type == DirectoryLister::DATE)
    std::sort(data->begin(), data->end(), CompareDate);
  else if (sort_type == DirectoryLister::FULL_PATH)
    std::sort(data->begin(), data->end(), CompareFullPath);
  else if (sort_type == DirectoryLister::ALPHA_DIRS_FIRST)
    std::sort(data->begin(), data->end(), CompareAlphaDirsFirst);
  else
    DCHECK_EQ(DirectoryLister::NO_SORT, sort_type);
}
}  
DirectoryLister::DirectoryLister(const base::FilePath& dir,
                                 DirectoryListerDelegate* delegate)
    : core_(new Core(dir, false, ALPHA_DIRS_FIRST, this)),
      delegate_(delegate) {
  DCHECK(delegate_);
  DCHECK(!dir.value().empty());
}
DirectoryLister::DirectoryLister(const base::FilePath& dir,
                                 bool recursive,
                                 SortType sort,
                                 DirectoryListerDelegate* delegate)
    : core_(new Core(dir, recursive, sort, this)),
      delegate_(delegate) {
  DCHECK(delegate_);
  DCHECK(!dir.value().empty());
}
DirectoryLister::~DirectoryLister() {
  Cancel();
}
bool DirectoryLister::Start() {
  return core_->Start();
}
void DirectoryLister::Cancel() {
  return core_->Cancel();
}
DirectoryLister::Core::Core(const base::FilePath& dir,
                            bool recursive,
                            SortType sort,
                            DirectoryLister* lister)
    : dir_(dir),
      recursive_(recursive),
      sort_(sort),
      lister_(lister) {
  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::Cancel() {
  lister_ = NULL;
}
void DirectoryLister::Core::StartInternal() {
  if (!base::DirectoryExists(dir_)) {
    origin_loop_->PostTask(
        FROM_HERE,
        base::Bind(&DirectoryLister::Core::OnDone, this, ERR_FILE_NOT_FOUND));
    return;
  }
  int types = base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES;
  if (!recursive_)
    types |= base::FileEnumerator::INCLUDE_DOT_DOT;
  base::FileEnumerator file_enum(dir_, recursive_, types);
  base::FilePath path;
  std::vector<DirectoryListerData> file_data;
  while (lister_ && !(path = file_enum.Next()).empty()) {
    DirectoryListerData data;
    data.info = file_enum.GetInfo();
    data.path = path;
    file_data.push_back(data);
    
  }
  SortData(&file_data, sort_);
  origin_loop_->PostTask(
      FROM_HERE,
      base::Bind(&DirectoryLister::Core::SendData, this, file_data));
  origin_loop_->PostTask(
      FROM_HERE,
      base::Bind(&DirectoryLister::Core::OnDone, this, OK));
}
void DirectoryLister::Core::SendData(
    const std::vector<DirectoryLister::DirectoryListerData>& data) {
  DCHECK(origin_loop_->BelongsToCurrentThread());
  
  
  for (size_t i = 0; lister_ && i < data.size(); ++i)
    lister_->OnReceivedData(data[i]);
}
void DirectoryLister::Core::OnDone(int error) {
  DCHECK(origin_loop_->BelongsToCurrentThread());
  if (lister_)
    lister_->OnDone(error);
}
void DirectoryLister::OnReceivedData(const DirectoryListerData& data) {
  delegate_->OnListFile(data);
}
void DirectoryLister::OnDone(int error) {
  delegate_->OnListDone(error);
}
}