blob: c476b76296a5a315f3911caf2a4f51f343ddb813 [file] [log] [blame]
// Copyright (c) 2010 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 "webkit/glue/plugins/pepper_directory_reader.h"
#include "base/logging.h"
#include "base/utf_string_conversions.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/dev/ppb_directory_reader_dev.h"
#include "webkit/glue/plugins/pepper_file_callbacks.h"
#include "webkit/glue/plugins/pepper_common.h"
#include "webkit/glue/plugins/pepper_file_ref.h"
#include "webkit/glue/plugins/pepper_file_system.h"
#include "webkit/glue/plugins/pepper_plugin_delegate.h"
#include "webkit/glue/plugins/pepper_plugin_instance.h"
#include "webkit/glue/plugins/pepper_plugin_module.h"
#include "webkit/glue/plugins/pepper_resource_tracker.h"
namespace pepper {
namespace {
std::string FilePathStringToUTF8String(const FilePath::StringType& str) {
#if defined(OS_WIN)
return WideToUTF8(str);
#elif defined(OS_POSIX)
return str;
#else
#error "Unsupported platform."
#endif
}
FilePath::StringType UTF8StringToFilePathString(const std::string& str) {
#if defined(OS_WIN)
return UTF8ToWide(str);
#elif defined(OS_POSIX)
return str;
#else
#error "Unsupported platform."
#endif
}
PP_Resource Create(PP_Resource directory_ref_id) {
scoped_refptr<FileRef> directory_ref(
Resource::GetAs<FileRef>(directory_ref_id));
if (!directory_ref)
return 0;
DirectoryReader* reader = new DirectoryReader(directory_ref);
return reader->GetReference();
}
PP_Bool IsDirectoryReader(PP_Resource resource) {
return BoolToPPBool(!!Resource::GetAs<DirectoryReader>(resource));
}
int32_t GetNextEntry(PP_Resource reader_id,
PP_DirectoryEntry_Dev* entry,
PP_CompletionCallback callback) {
scoped_refptr<DirectoryReader> reader(
Resource::GetAs<DirectoryReader>(reader_id));
if (!reader)
return PP_ERROR_BADRESOURCE;
return reader->GetNextEntry(entry, callback);
}
const PPB_DirectoryReader_Dev ppb_directoryreader = {
&Create,
&IsDirectoryReader,
&GetNextEntry
};
} // namespace
DirectoryReader::DirectoryReader(FileRef* directory_ref)
: Resource(directory_ref->module()),
directory_ref_(directory_ref),
has_more_(true),
entry_(NULL) {
}
DirectoryReader::~DirectoryReader() {
}
const PPB_DirectoryReader_Dev* DirectoryReader::GetInterface() {
return &ppb_directoryreader;
}
int32_t DirectoryReader::GetNextEntry(PP_DirectoryEntry_Dev* entry,
PP_CompletionCallback callback) {
if (directory_ref_->GetFileSystemType() == PP_FILESYSTEMTYPE_EXTERNAL)
return PP_ERROR_FAILED;
entry_ = entry;
if (FillUpEntry()) {
entry_ = NULL;
return PP_OK;
}
PluginInstance* instance = directory_ref_->GetFileSystem()->instance();
if (!instance->delegate()->ReadDirectory(
directory_ref_->GetSystemPath(),
new FileCallbacks(instance->module()->AsWeakPtr(),
callback, NULL, NULL, this)))
return PP_ERROR_FAILED;
return PP_ERROR_WOULDBLOCK;
}
void DirectoryReader::AddNewEntries(
const std::vector<base::FileUtilProxy::Entry>& entries, bool has_more) {
DCHECK(!entries.empty());
has_more_ = has_more;
std::string dir_path = directory_ref_->GetPath();
if (dir_path[dir_path.size() - 1] != '/')
dir_path += '/';
FilePath::StringType dir_file_path = UTF8StringToFilePathString(dir_path);
for (std::vector<base::FileUtilProxy::Entry>::const_iterator it =
entries.begin(); it != entries.end(); it++) {
base::FileUtilProxy::Entry entry;
entry.name = dir_file_path + it->name;
entry.is_directory = it->is_directory;
entries_.push(entry);
}
FillUpEntry();
entry_ = NULL;
}
bool DirectoryReader::FillUpEntry() {
DCHECK(entry_);
if (!entries_.empty()) {
base::FileUtilProxy::Entry dir_entry = entries_.front();
entries_.pop();
if (entry_->file_ref)
ResourceTracker::Get()->UnrefResource(entry_->file_ref);
FileRef* file_ref = new FileRef(module(), directory_ref_->GetFileSystem(),
FilePathStringToUTF8String(dir_entry.name));
entry_->file_ref = file_ref->GetReference();
entry_->file_type =
(dir_entry.is_directory ? PP_FILETYPE_DIRECTORY : PP_FILETYPE_REGULAR);
return true;
}
if (!has_more_) {
entry_->file_ref = 0;
return true;
}
return false;
}
} // namespace pepper