Index: chrome/browser/file_select_helper.cc |
=================================================================== |
--- chrome/browser/file_select_helper.cc (revision 76768) |
+++ chrome/browser/file_select_helper.cc (working copy) |
@@ -21,6 +21,15 @@ |
#include "grit/generated_resources.h" |
#include "ui/base/l10n/l10n_util.h" |
+namespace { |
+ |
+// There is only one file-selection happening at any given time, |
+// so we allocate an enumeration ID for that purpose. All IDs from |
+// the renderer must start at 0 and increase. |
+static const int kFileSelectEnumerationId = -1; |
+ |
+} |
+ |
FileSelectHelper::FileSelectHelper(Profile* profile) |
: profile_(profile), |
render_view_host_(NULL), |
@@ -34,10 +43,17 @@ |
if (select_file_dialog_.get()) |
select_file_dialog_->ListenerDestroyed(); |
- // Stop any pending directory enumeration and prevent a callback. |
- if (directory_lister_.get()) { |
- directory_lister_->set_delegate(NULL); |
- directory_lister_->Cancel(); |
+ // Stop any pending directory enumeration, prevent a callback, and free |
+ // allocated memory. |
+ std::map<int, ActiveDirectoryEnumeration*>::iterator iter; |
+ for (iter = directory_enumerations_.begin(); |
+ iter != directory_enumerations_.end(); |
+ ++iter) { |
+ if (iter->second->lister_.get()) { |
+ iter->second->lister_->set_delegate(NULL); |
+ iter->second->lister_->Cancel(); |
+ } |
+ delete iter->second; |
} |
} |
@@ -49,7 +65,7 @@ |
profile_->set_last_selected_directory(path.DirName()); |
if (dialog_type_ == SelectFileDialog::SELECT_FOLDER) { |
- DirectorySelected(path); |
+ StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_); |
return; |
} |
@@ -84,40 +100,55 @@ |
render_view_host_ = NULL; |
} |
-void FileSelectHelper::DirectorySelected(const FilePath& path) { |
- directory_lister_ = new net::DirectoryLister(path, |
- true, |
- net::DirectoryLister::NO_SORT, |
- this); |
- if (!directory_lister_->Start()) |
- FileSelectionCanceled(NULL); |
+void FileSelectHelper::StartNewEnumeration(const FilePath& path, |
+ int request_id, |
+ RenderViewHost* render_view_host) { |
+ scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); |
+ entry->rvh_ = render_view_host; |
+ entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); |
+ entry->lister_ = new net::DirectoryLister(path, |
+ true, |
+ net::DirectoryLister::NO_SORT, |
+ entry->delegate_.get()); |
+ if (!entry->lister_->Start()) { |
+ if (request_id == kFileSelectEnumerationId) |
+ FileSelectionCanceled(NULL); |
+ else |
+ render_view_host->DirectoryEnumerationFinished(request_id, |
+ entry->results_); |
+ } else { |
+ directory_enumerations_[request_id] = entry.release(); |
+ } |
} |
void FileSelectHelper::OnListFile( |
+ int id, |
const net::DirectoryLister::DirectoryListerData& data) { |
+ ActiveDirectoryEnumeration* entry = directory_enumerations_[id]; |
+ |
// Directory upload returns directories via a "." file, so that |
// empty directories are included. This util call just checks |
// the flags in the structure; there's no file I/O going on. |
if (file_util::FileEnumerator::IsDirectory(data.info)) |
- directory_lister_results_.push_back( |
- data.path.Append(FILE_PATH_LITERAL("."))); |
+ entry->results_.push_back(data.path.Append(FILE_PATH_LITERAL("."))); |
else |
- directory_lister_results_.push_back(data.path); |
+ entry->results_.push_back(data.path); |
} |
-void FileSelectHelper::OnListDone(int error) { |
- if (!render_view_host_) |
+void FileSelectHelper::OnListDone(int id, int error) { |
+ // This entry needs to be cleaned up when this function is done. |
+ scoped_ptr<ActiveDirectoryEnumeration> entry(directory_enumerations_[id]); |
+ directory_enumerations_.erase(id); |
+ if (!entry->rvh_) |
return; |
- |
if (error) { |
FileSelectionCanceled(NULL); |
return; |
} |
- |
- render_view_host_->FilesSelectedInChooser(directory_lister_results_); |
- render_view_host_ = NULL; |
- directory_lister_ = NULL; |
- directory_lister_results_.clear(); |
+ if (id == kFileSelectEnumerationId) |
+ entry->rvh_->FilesSelectedInChooser(entry->results_); |
+ else |
+ entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); |
} |
SelectFileDialog::FileTypeInfo* FileSelectHelper::GetFileTypesFromAcceptType( |
@@ -238,6 +269,13 @@ |
NULL); |
} |
+void FileSelectHelper::EnumerateDirectory(int request_id, |
+ RenderViewHost* render_view_host, |
+ const FilePath& path) { |
+ DCHECK_NE(kFileSelectEnumerationId, request_id); |
+ StartNewEnumeration(path, request_id, render_view_host); |
+} |
+ |
void FileSelectHelper::Observe(NotificationType type, |
const NotificationSource& source, |
const NotificationDetails& details) { |