| Index: chrome/browser/file_select_helper.cc
|
| diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc
|
| index fa0004ccb2edabad900f27e883d9b98fbe83c6a6..3aaa9ce796d547f7492ebce2bdbeea06e199fe39 100644
|
| --- a/chrome/browser/file_select_helper.cc
|
| +++ b/chrome/browser/file_select_helper.cc
|
| @@ -61,6 +61,11 @@ std::vector<ui::SelectedFileInfo> FilePathListToSelectedFileInfoList(
|
| return selected_files;
|
| }
|
|
|
| +void DeleteFiles(const std::vector<base::FilePath>& paths) {
|
| + for (auto& file_path : paths)
|
| + base::DeleteFile(file_path, false);
|
| +}
|
| +
|
| } // namespace
|
|
|
| struct FileSelectHelper::ActiveDirectoryEnumeration {
|
| @@ -117,11 +122,13 @@ void FileSelectHelper::FileSelectedWithExtraInfo(
|
| const ui::SelectedFileInfo& file,
|
| int index,
|
| void* params) {
|
| - if (!render_view_host_)
|
| - return;
|
| -
|
| profile_->set_last_selected_directory(file.file_path.DirName());
|
|
|
| + if (!render_view_host_) {
|
| + RunFileChooserEnd();
|
| + return;
|
| + }
|
| +
|
| const base::FilePath& path = file.local_path;
|
| if (dialog_type_ == ui::SelectFileDialog::SELECT_UPLOAD_FOLDER) {
|
| StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_);
|
| @@ -130,10 +137,15 @@ void FileSelectHelper::FileSelectedWithExtraInfo(
|
|
|
| std::vector<ui::SelectedFileInfo> files;
|
| files.push_back(file);
|
| - NotifyRenderViewHost(render_view_host_, files, dialog_mode_);
|
|
|
| - // No members should be accessed from here on.
|
| - RunFileChooserEnd();
|
| +#if defined(OS_MACOSX) && !defined(OS_IOS)
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::FILE_USER_BLOCKING,
|
| + FROM_HERE,
|
| + base::Bind(&FileSelectHelper::ProcessSelectedFilesMac, this, files));
|
| +#else
|
| + NotifyRenderViewHostAndEnd(files);
|
| +#endif // defined(OS_MACOSX) && !defined(OS_IOS)
|
| }
|
|
|
| void FileSelectHelper::MultiFilesSelected(
|
| @@ -150,27 +162,19 @@ void FileSelectHelper::MultiFilesSelectedWithExtraInfo(
|
| void* params) {
|
| if (!files.empty())
|
| profile_->set_last_selected_directory(files[0].file_path.DirName());
|
| - if (!render_view_host_)
|
| - return;
|
|
|
| - NotifyRenderViewHost(render_view_host_, files, dialog_mode_);
|
| -
|
| - // No members should be accessed from here on.
|
| - RunFileChooserEnd();
|
| +#if defined(OS_MACOSX) && !defined(OS_IOS)
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::FILE_USER_BLOCKING,
|
| + FROM_HERE,
|
| + base::Bind(&FileSelectHelper::ProcessSelectedFilesMac, this, files));
|
| +#else
|
| + NotifyRenderViewHostAndEnd(files);
|
| +#endif // defined(OS_MACOSX) && !defined(OS_IOS)
|
| }
|
|
|
| void FileSelectHelper::FileSelectionCanceled(void* params) {
|
| - if (!render_view_host_)
|
| - return;
|
| -
|
| - // If the user cancels choosing a file to upload we pass back an
|
| - // empty vector.
|
| - NotifyRenderViewHost(
|
| - render_view_host_, std::vector<ui::SelectedFileInfo>(),
|
| - dialog_mode_);
|
| -
|
| - // No members should be accessed from here on.
|
| - RunFileChooserEnd();
|
| + NotifyRenderViewHostAndEnd(std::vector<ui::SelectedFileInfo>());
|
| }
|
|
|
| void FileSelectHelper::StartNewEnumeration(const base::FilePath& path,
|
| @@ -228,6 +232,22 @@ void FileSelectHelper::OnListDone(int id, int error) {
|
| EnumerateDirectoryEnd();
|
| }
|
|
|
| +void FileSelectHelper::NotifyRenderViewHostAndEnd(
|
| + const std::vector<ui::SelectedFileInfo>& files) {
|
| + if (render_view_host_)
|
| + NotifyRenderViewHost(render_view_host_, files, dialog_mode_);
|
| +
|
| + // No members should be accessed from here on.
|
| + RunFileChooserEnd();
|
| +}
|
| +
|
| +void FileSelectHelper::DeleteTemporaryFiles() {
|
| + BrowserThread::PostTask(BrowserThread::FILE,
|
| + FROM_HERE,
|
| + base::Bind(&DeleteFiles, temporary_files_));
|
| + temporary_files_.clear();
|
| +}
|
| +
|
| scoped_ptr<ui::SelectFileDialog::FileTypeInfo>
|
| FileSelectHelper::GetFileTypesFromAcceptType(
|
| const std::vector<base::string16>& accept_types) {
|
| @@ -326,8 +346,12 @@ void FileSelectHelper::RunFileChooser(RenderViewHost* render_view_host,
|
| render_view_host_ = render_view_host;
|
| web_contents_ = web_contents;
|
| notification_registrar_.RemoveAll();
|
| + notification_registrar_.Add(this,
|
| + content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
|
| + content::Source<WebContents>(web_contents_));
|
| notification_registrar_.Add(
|
| - this, content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
|
| + this,
|
| + content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
|
| content::Source<RenderWidgetHost>(render_view_host_));
|
| notification_registrar_.Add(
|
| this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
|
| @@ -424,6 +448,12 @@ void FileSelectHelper::RunFileChooserOnUIThread(
|
| // chooser dialog. Perform any cleanup and release the reference we added
|
| // in RunFileChooser().
|
| void FileSelectHelper::RunFileChooserEnd() {
|
| + // If there are temporary files, then this instance needs to stick around
|
| + // until web_contents_ is destroyed, so that this instance can delete the
|
| + // temporary files.
|
| + if (!temporary_files_.empty())
|
| + return;
|
| +
|
| render_view_host_ = NULL;
|
| web_contents_ = NULL;
|
| Release();
|
| @@ -463,9 +493,20 @@ void FileSelectHelper::Observe(int type,
|
| case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: {
|
| DCHECK(content::Source<WebContents>(source).ptr() == web_contents_);
|
| web_contents_ = NULL;
|
| - break;
|
| }
|
|
|
| + // Intentional fall through.
|
| + case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED:
|
| + if (!temporary_files_.empty()) {
|
| + DeleteTemporaryFiles();
|
| +
|
| + // Now that the temporary files have been scheduled for deletion, there
|
| + // is no longer any reason to keep this instance around.
|
| + Release();
|
| + }
|
| +
|
| + break;
|
| +
|
| default:
|
| NOTREACHED();
|
| }
|
|
|