| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/file_select_helper.h" | 5 #include "chrome/browser/file_select_helper.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 std::vector<ui::SelectedFileInfo> FilePathListToSelectedFileInfoList( | 54 std::vector<ui::SelectedFileInfo> FilePathListToSelectedFileInfoList( |
| 55 const std::vector<base::FilePath>& paths) { | 55 const std::vector<base::FilePath>& paths) { |
| 56 std::vector<ui::SelectedFileInfo> selected_files; | 56 std::vector<ui::SelectedFileInfo> selected_files; |
| 57 for (size_t i = 0; i < paths.size(); ++i) { | 57 for (size_t i = 0; i < paths.size(); ++i) { |
| 58 selected_files.push_back( | 58 selected_files.push_back( |
| 59 ui::SelectedFileInfo(paths[i], paths[i])); | 59 ui::SelectedFileInfo(paths[i], paths[i])); |
| 60 } | 60 } |
| 61 return selected_files; | 61 return selected_files; |
| 62 } | 62 } |
| 63 | 63 |
| 64 void DeleteFiles(const std::vector<base::FilePath>& paths) { |
| 65 for (auto& file_path : paths) |
| 66 base::DeleteFile(file_path, false); |
| 67 } |
| 68 |
| 64 } // namespace | 69 } // namespace |
| 65 | 70 |
| 66 struct FileSelectHelper::ActiveDirectoryEnumeration { | 71 struct FileSelectHelper::ActiveDirectoryEnumeration { |
| 67 ActiveDirectoryEnumeration() : rvh_(NULL) {} | 72 ActiveDirectoryEnumeration() : rvh_(NULL) {} |
| 68 | 73 |
| 69 scoped_ptr<DirectoryListerDispatchDelegate> delegate_; | 74 scoped_ptr<DirectoryListerDispatchDelegate> delegate_; |
| 70 scoped_ptr<net::DirectoryLister> lister_; | 75 scoped_ptr<net::DirectoryLister> lister_; |
| 71 RenderViewHost* rvh_; | 76 RenderViewHost* rvh_; |
| 72 std::vector<base::FilePath> results_; | 77 std::vector<base::FilePath> results_; |
| 73 }; | 78 }; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 | 115 |
| 111 void FileSelectHelper::FileSelected(const base::FilePath& path, | 116 void FileSelectHelper::FileSelected(const base::FilePath& path, |
| 112 int index, void* params) { | 117 int index, void* params) { |
| 113 FileSelectedWithExtraInfo(ui::SelectedFileInfo(path, path), index, params); | 118 FileSelectedWithExtraInfo(ui::SelectedFileInfo(path, path), index, params); |
| 114 } | 119 } |
| 115 | 120 |
| 116 void FileSelectHelper::FileSelectedWithExtraInfo( | 121 void FileSelectHelper::FileSelectedWithExtraInfo( |
| 117 const ui::SelectedFileInfo& file, | 122 const ui::SelectedFileInfo& file, |
| 118 int index, | 123 int index, |
| 119 void* params) { | 124 void* params) { |
| 120 if (!render_view_host_) | 125 profile_->set_last_selected_directory(file.file_path.DirName()); |
| 126 |
| 127 if (!render_view_host_) { |
| 128 RunFileChooserEnd(); |
| 121 return; | 129 return; |
| 122 | 130 } |
| 123 profile_->set_last_selected_directory(file.file_path.DirName()); | |
| 124 | 131 |
| 125 const base::FilePath& path = file.local_path; | 132 const base::FilePath& path = file.local_path; |
| 126 if (dialog_type_ == ui::SelectFileDialog::SELECT_UPLOAD_FOLDER) { | 133 if (dialog_type_ == ui::SelectFileDialog::SELECT_UPLOAD_FOLDER) { |
| 127 StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_); | 134 StartNewEnumeration(path, kFileSelectEnumerationId, render_view_host_); |
| 128 return; | 135 return; |
| 129 } | 136 } |
| 130 | 137 |
| 131 std::vector<ui::SelectedFileInfo> files; | 138 std::vector<ui::SelectedFileInfo> files; |
| 132 files.push_back(file); | 139 files.push_back(file); |
| 133 NotifyRenderViewHost(render_view_host_, files, dialog_mode_); | |
| 134 | 140 |
| 135 // No members should be accessed from here on. | 141 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 136 RunFileChooserEnd(); | 142 content::BrowserThread::PostTask( |
| 143 content::BrowserThread::FILE_USER_BLOCKING, |
| 144 FROM_HERE, |
| 145 base::Bind(&FileSelectHelper::ProcessSelectedFilesMac, this, files)); |
| 146 #else |
| 147 NotifyRenderViewHostAndEnd(files); |
| 148 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 137 } | 149 } |
| 138 | 150 |
| 139 void FileSelectHelper::MultiFilesSelected( | 151 void FileSelectHelper::MultiFilesSelected( |
| 140 const std::vector<base::FilePath>& files, | 152 const std::vector<base::FilePath>& files, |
| 141 void* params) { | 153 void* params) { |
| 142 std::vector<ui::SelectedFileInfo> selected_files = | 154 std::vector<ui::SelectedFileInfo> selected_files = |
| 143 FilePathListToSelectedFileInfoList(files); | 155 FilePathListToSelectedFileInfoList(files); |
| 144 | 156 |
| 145 MultiFilesSelectedWithExtraInfo(selected_files, params); | 157 MultiFilesSelectedWithExtraInfo(selected_files, params); |
| 146 } | 158 } |
| 147 | 159 |
| 148 void FileSelectHelper::MultiFilesSelectedWithExtraInfo( | 160 void FileSelectHelper::MultiFilesSelectedWithExtraInfo( |
| 149 const std::vector<ui::SelectedFileInfo>& files, | 161 const std::vector<ui::SelectedFileInfo>& files, |
| 150 void* params) { | 162 void* params) { |
| 151 if (!files.empty()) | 163 if (!files.empty()) |
| 152 profile_->set_last_selected_directory(files[0].file_path.DirName()); | 164 profile_->set_last_selected_directory(files[0].file_path.DirName()); |
| 153 if (!render_view_host_) | |
| 154 return; | |
| 155 | 165 |
| 156 NotifyRenderViewHost(render_view_host_, files, dialog_mode_); | 166 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 157 | 167 content::BrowserThread::PostTask( |
| 158 // No members should be accessed from here on. | 168 content::BrowserThread::FILE_USER_BLOCKING, |
| 159 RunFileChooserEnd(); | 169 FROM_HERE, |
| 170 base::Bind(&FileSelectHelper::ProcessSelectedFilesMac, this, files)); |
| 171 #else |
| 172 NotifyRenderViewHostAndEnd(files); |
| 173 #endif // defined(OS_MACOSX) && !defined(OS_IOS) |
| 160 } | 174 } |
| 161 | 175 |
| 162 void FileSelectHelper::FileSelectionCanceled(void* params) { | 176 void FileSelectHelper::FileSelectionCanceled(void* params) { |
| 163 if (!render_view_host_) | 177 NotifyRenderViewHostAndEnd(std::vector<ui::SelectedFileInfo>()); |
| 164 return; | |
| 165 | |
| 166 // If the user cancels choosing a file to upload we pass back an | |
| 167 // empty vector. | |
| 168 NotifyRenderViewHost( | |
| 169 render_view_host_, std::vector<ui::SelectedFileInfo>(), | |
| 170 dialog_mode_); | |
| 171 | |
| 172 // No members should be accessed from here on. | |
| 173 RunFileChooserEnd(); | |
| 174 } | 178 } |
| 175 | 179 |
| 176 void FileSelectHelper::StartNewEnumeration(const base::FilePath& path, | 180 void FileSelectHelper::StartNewEnumeration(const base::FilePath& path, |
| 177 int request_id, | 181 int request_id, |
| 178 RenderViewHost* render_view_host) { | 182 RenderViewHost* render_view_host) { |
| 179 scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); | 183 scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); |
| 180 entry->rvh_ = render_view_host; | 184 entry->rvh_ = render_view_host; |
| 181 entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); | 185 entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); |
| 182 entry->lister_.reset(new net::DirectoryLister(path, | 186 entry->lister_.reset(new net::DirectoryLister(path, |
| 183 true, | 187 true, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 FilePathListToSelectedFileInfoList(entry->results_); | 225 FilePathListToSelectedFileInfoList(entry->results_); |
| 222 | 226 |
| 223 if (id == kFileSelectEnumerationId) | 227 if (id == kFileSelectEnumerationId) |
| 224 NotifyRenderViewHost(entry->rvh_, selected_files, dialog_mode_); | 228 NotifyRenderViewHost(entry->rvh_, selected_files, dialog_mode_); |
| 225 else | 229 else |
| 226 entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); | 230 entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); |
| 227 | 231 |
| 228 EnumerateDirectoryEnd(); | 232 EnumerateDirectoryEnd(); |
| 229 } | 233 } |
| 230 | 234 |
| 235 void FileSelectHelper::NotifyRenderViewHostAndEnd( |
| 236 const std::vector<ui::SelectedFileInfo>& files) { |
| 237 if (render_view_host_) |
| 238 NotifyRenderViewHost(render_view_host_, files, dialog_mode_); |
| 239 |
| 240 // No members should be accessed from here on. |
| 241 RunFileChooserEnd(); |
| 242 } |
| 243 |
| 244 void FileSelectHelper::DeleteTemporaryFiles() { |
| 245 BrowserThread::PostTask(BrowserThread::FILE, |
| 246 FROM_HERE, |
| 247 base::Bind(&DeleteFiles, temporary_files_)); |
| 248 temporary_files_.clear(); |
| 249 } |
| 250 |
| 231 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> | 251 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> |
| 232 FileSelectHelper::GetFileTypesFromAcceptType( | 252 FileSelectHelper::GetFileTypesFromAcceptType( |
| 233 const std::vector<base::string16>& accept_types) { | 253 const std::vector<base::string16>& accept_types) { |
| 234 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> base_file_type( | 254 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> base_file_type( |
| 235 new ui::SelectFileDialog::FileTypeInfo()); | 255 new ui::SelectFileDialog::FileTypeInfo()); |
| 236 if (accept_types.empty()) | 256 if (accept_types.empty()) |
| 237 return base_file_type.Pass(); | 257 return base_file_type.Pass(); |
| 238 | 258 |
| 239 // Create FileTypeInfo and pre-allocate for the first extension list. | 259 // Create FileTypeInfo and pre-allocate for the first extension list. |
| 240 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> file_type( | 260 scoped_ptr<ui::SelectFileDialog::FileTypeInfo> file_type( |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 } | 339 } |
| 320 | 340 |
| 321 void FileSelectHelper::RunFileChooser(RenderViewHost* render_view_host, | 341 void FileSelectHelper::RunFileChooser(RenderViewHost* render_view_host, |
| 322 content::WebContents* web_contents, | 342 content::WebContents* web_contents, |
| 323 const FileChooserParams& params) { | 343 const FileChooserParams& params) { |
| 324 DCHECK(!render_view_host_); | 344 DCHECK(!render_view_host_); |
| 325 DCHECK(!web_contents_); | 345 DCHECK(!web_contents_); |
| 326 render_view_host_ = render_view_host; | 346 render_view_host_ = render_view_host; |
| 327 web_contents_ = web_contents; | 347 web_contents_ = web_contents; |
| 328 notification_registrar_.RemoveAll(); | 348 notification_registrar_.RemoveAll(); |
| 349 notification_registrar_.Add(this, |
| 350 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
| 351 content::Source<WebContents>(web_contents_)); |
| 329 notification_registrar_.Add( | 352 notification_registrar_.Add( |
| 330 this, content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, | 353 this, |
| 354 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, |
| 331 content::Source<RenderWidgetHost>(render_view_host_)); | 355 content::Source<RenderWidgetHost>(render_view_host_)); |
| 332 notification_registrar_.Add( | 356 notification_registrar_.Add( |
| 333 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 357 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 334 content::Source<WebContents>(web_contents_)); | 358 content::Source<WebContents>(web_contents_)); |
| 335 | 359 |
| 336 BrowserThread::PostTask( | 360 BrowserThread::PostTask( |
| 337 BrowserThread::FILE, FROM_HERE, | 361 BrowserThread::FILE, FROM_HERE, |
| 338 base::Bind(&FileSelectHelper::RunFileChooserOnFileThread, this, params)); | 362 base::Bind(&FileSelectHelper::RunFileChooserOnFileThread, this, params)); |
| 339 | 363 |
| 340 // Because this class returns notifications to the RenderViewHost, it is | 364 // Because this class returns notifications to the RenderViewHost, it is |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 NULL); | 441 NULL); |
| 418 #endif | 442 #endif |
| 419 | 443 |
| 420 select_file_types_.reset(); | 444 select_file_types_.reset(); |
| 421 } | 445 } |
| 422 | 446 |
| 423 // This method is called when we receive the last callback from the file | 447 // This method is called when we receive the last callback from the file |
| 424 // chooser dialog. Perform any cleanup and release the reference we added | 448 // chooser dialog. Perform any cleanup and release the reference we added |
| 425 // in RunFileChooser(). | 449 // in RunFileChooser(). |
| 426 void FileSelectHelper::RunFileChooserEnd() { | 450 void FileSelectHelper::RunFileChooserEnd() { |
| 451 // If there are temporary files, then this instance needs to stick around |
| 452 // until web_contents_ is destroyed, so that this instance can delete the |
| 453 // temporary files. |
| 454 if (!temporary_files_.empty()) |
| 455 return; |
| 456 |
| 427 render_view_host_ = NULL; | 457 render_view_host_ = NULL; |
| 428 web_contents_ = NULL; | 458 web_contents_ = NULL; |
| 429 Release(); | 459 Release(); |
| 430 } | 460 } |
| 431 | 461 |
| 432 void FileSelectHelper::EnumerateDirectory(int request_id, | 462 void FileSelectHelper::EnumerateDirectory(int request_id, |
| 433 RenderViewHost* render_view_host, | 463 RenderViewHost* render_view_host, |
| 434 const base::FilePath& path) { | 464 const base::FilePath& path) { |
| 435 | 465 |
| 436 // Because this class returns notifications to the RenderViewHost, it is | 466 // Because this class returns notifications to the RenderViewHost, it is |
| (...skipping 19 matching lines...) Expand all Loading... |
| 456 case content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { | 486 case content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: { |
| 457 DCHECK(content::Source<RenderWidgetHost>(source).ptr() == | 487 DCHECK(content::Source<RenderWidgetHost>(source).ptr() == |
| 458 render_view_host_); | 488 render_view_host_); |
| 459 render_view_host_ = NULL; | 489 render_view_host_ = NULL; |
| 460 break; | 490 break; |
| 461 } | 491 } |
| 462 | 492 |
| 463 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { | 493 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { |
| 464 DCHECK(content::Source<WebContents>(source).ptr() == web_contents_); | 494 DCHECK(content::Source<WebContents>(source).ptr() == web_contents_); |
| 465 web_contents_ = NULL; | 495 web_contents_ = NULL; |
| 496 } |
| 497 |
| 498 // Intentional fall through. |
| 499 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: |
| 500 if (!temporary_files_.empty()) { |
| 501 DeleteTemporaryFiles(); |
| 502 |
| 503 // Now that the temporary files have been scheduled for deletion, there |
| 504 // is no longer any reason to keep this instance around. |
| 505 Release(); |
| 506 } |
| 507 |
| 466 break; | 508 break; |
| 467 } | |
| 468 | 509 |
| 469 default: | 510 default: |
| 470 NOTREACHED(); | 511 NOTREACHED(); |
| 471 } | 512 } |
| 472 } | 513 } |
| 473 | 514 |
| 474 // static | 515 // static |
| 475 bool FileSelectHelper::IsAcceptTypeValid(const std::string& accept_type) { | 516 bool FileSelectHelper::IsAcceptTypeValid(const std::string& accept_type) { |
| 476 // TODO(raymes): This only does some basic checks, extend to test more cases. | 517 // TODO(raymes): This only does some basic checks, extend to test more cases. |
| 477 // A 1 character accept type will always be invalid (either a "." in the case | 518 // A 1 character accept type will always be invalid (either a "." in the case |
| 478 // of an extension or a "/" in the case of a MIME type). | 519 // of an extension or a "/" in the case of a MIME type). |
| 479 std::string unused; | 520 std::string unused; |
| 480 if (accept_type.length() <= 1 || | 521 if (accept_type.length() <= 1 || |
| 481 base::StringToLowerASCII(accept_type) != accept_type || | 522 base::StringToLowerASCII(accept_type) != accept_type || |
| 482 base::TrimWhitespaceASCII(accept_type, base::TRIM_ALL, &unused) != | 523 base::TrimWhitespaceASCII(accept_type, base::TRIM_ALL, &unused) != |
| 483 base::TRIM_NONE) { | 524 base::TRIM_NONE) { |
| 484 return false; | 525 return false; |
| 485 } | 526 } |
| 486 return true; | 527 return true; |
| 487 } | 528 } |
| OLD | NEW |