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 <stddef.h> | 5 #include <stddef.h> |
6 #include <X11/Xlib.h> | 6 #include <X11/Xlib.h> |
7 | 7 |
| 8 #include <memory> |
8 #include <set> | 9 #include <set> |
9 | 10 |
10 #include "base/bind.h" | 11 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/macros.h" | 15 #include "base/macros.h" |
15 #include "base/nix/mime_util_xdg.h" | 16 #include "base/nix/mime_util_xdg.h" |
16 #include "base/nix/xdg_util.h" | 17 #include "base/nix/xdg_util.h" |
17 #include "base/process/launch.h" | 18 #include "base/process/launch.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 const FileTypeInfo* file_types, | 68 const FileTypeInfo* file_types, |
68 int file_type_index, | 69 int file_type_index, |
69 const base::FilePath::StringType& default_extension, | 70 const base::FilePath::StringType& default_extension, |
70 gfx::NativeWindow owning_window, | 71 gfx::NativeWindow owning_window, |
71 void* params) override; | 72 void* params) override; |
72 | 73 |
73 private: | 74 private: |
74 bool HasMultipleFileTypeChoicesImpl() override; | 75 bool HasMultipleFileTypeChoicesImpl() override; |
75 | 76 |
76 struct KDialogParams { | 77 struct KDialogParams { |
77 KDialogParams(const std::string& type, const std::string& title, | 78 KDialogParams(const std::string& type, |
78 const base::FilePath& default_path, XID parent, | 79 const std::string& title, |
79 bool file_operation, bool multiple_selection, | 80 const base::FilePath& default_path, |
80 void* kdialog_params, | 81 XID parent, |
81 void (SelectFileDialogImplKDE::*callback)(XID, | 82 bool file_operation, |
82 const std::string&, | 83 bool multiple_selection) |
83 int, void*)) | 84 : type(type), |
84 : type(type), title(title), default_path(default_path), parent(parent), | 85 title(title), |
| 86 default_path(default_path), |
| 87 parent(parent), |
85 file_operation(file_operation), | 88 file_operation(file_operation), |
86 multiple_selection(multiple_selection), | 89 multiple_selection(multiple_selection) {} |
87 kdialog_params(kdialog_params), callback(callback) { | |
88 } | |
89 | 90 |
90 std::string type; | 91 std::string type; |
91 std::string title; | 92 std::string title; |
92 base::FilePath default_path; | 93 base::FilePath default_path; |
93 XID parent; | 94 XID parent; |
94 bool file_operation; | 95 bool file_operation; |
95 bool multiple_selection; | 96 bool multiple_selection; |
96 void* kdialog_params; | 97 }; |
97 void (SelectFileDialogImplKDE::*callback)(XID, const std::string&, | 98 |
98 int, void*); | 99 struct KDialogOutputParams { |
| 100 std::string output; |
| 101 int exit_code; |
99 }; | 102 }; |
100 | 103 |
101 // Get the filters from |file_types_| and concatenate them into | 104 // Get the filters from |file_types_| and concatenate them into |
102 // |filter_string|. | 105 // |filter_string|. |
103 std::string GetMimeTypeFilterString(); | 106 std::string GetMimeTypeFilterString(); |
104 | 107 |
105 // Get KDialog command line representing the Argv array for KDialog. | 108 // Get KDialog command line representing the Argv array for KDialog. |
106 void GetKDialogCommandLine(const std::string& type, | 109 void GetKDialogCommandLine(const std::string& type, |
107 const std::string& title, | 110 const std::string& title, |
108 const base::FilePath& default_path, | 111 const base::FilePath& default_path, |
109 XID parent, | 112 XID parent, |
110 bool file_operation, | 113 bool file_operation, |
111 bool multiple_selection, | 114 bool multiple_selection, |
112 base::CommandLine* command_line); | 115 base::CommandLine* command_line); |
113 | 116 |
114 // Call KDialog on the FILE thread and post results back to the UI thread. | 117 // Call KDialog on the FILE thread and return the results. |
115 void CallKDialogOutput(const KDialogParams& params); | 118 std::unique_ptr<KDialogOutputParams> CallKDialogOutput( |
| 119 const KDialogParams& params); |
116 | 120 |
117 // Notifies the listener that a single file was chosen. | 121 // Notifies the listener that a single file was chosen. |
118 void FileSelected(const base::FilePath& path, void* params); | 122 void FileSelected(const base::FilePath& path, void* params); |
119 | 123 |
120 // Notifies the listener that multiple files were chosen. | 124 // Notifies the listener that multiple files were chosen. |
121 void MultiFilesSelected(const std::vector<base::FilePath>& files, | 125 void MultiFilesSelected(const std::vector<base::FilePath>& files, |
122 void* params); | 126 void* params); |
123 | 127 |
124 // Notifies the listener that no file was chosen (the action was canceled). | 128 // Notifies the listener that no file was chosen (the action was canceled). |
125 // Dialog is passed so we can find that |params| pointer that was passed to | 129 // Dialog is passed so we can find that |params| pointer that was passed to |
(...skipping 12 matching lines...) Expand all Loading... |
138 void CreateMultiFileOpenDialog(const std::string& title, | 142 void CreateMultiFileOpenDialog(const std::string& title, |
139 const base::FilePath& default_path, | 143 const base::FilePath& default_path, |
140 XID parent, void* params); | 144 XID parent, void* params); |
141 | 145 |
142 void CreateSaveAsDialog(const std::string& title, | 146 void CreateSaveAsDialog(const std::string& title, |
143 const base::FilePath& default_path, | 147 const base::FilePath& default_path, |
144 XID parent, void* params); | 148 XID parent, void* params); |
145 | 149 |
146 // Common function for OnSelectSingleFileDialogResponse and | 150 // Common function for OnSelectSingleFileDialogResponse and |
147 // OnSelectSingleFolderDialogResponse. | 151 // OnSelectSingleFolderDialogResponse. |
148 void SelectSingleFileHelper(const std::string& output, int exit_code, | 152 void SelectSingleFileHelper(void* params, |
149 void* params, bool allow_folder); | 153 bool allow_folder, |
| 154 std::unique_ptr<KDialogOutputParams> results); |
150 | 155 |
151 void OnSelectSingleFileDialogResponse(XID parent, | 156 void OnSelectSingleFileDialogResponse( |
152 const std::string& output, | 157 XID parent, |
153 int exit_code, void* params); | 158 void* params, |
154 void OnSelectMultiFileDialogResponse(XID parent, | 159 std::unique_ptr<KDialogOutputParams> results); |
155 const std::string& output, | 160 void OnSelectMultiFileDialogResponse( |
156 int exit_code, void* params); | 161 XID parent, |
157 void OnSelectSingleFolderDialogResponse(XID parent, | 162 void* params, |
158 const std::string& output, | 163 std::unique_ptr<KDialogOutputParams> results); |
159 int exit_code, void* params); | 164 void OnSelectSingleFolderDialogResponse( |
| 165 XID parent, |
| 166 void* params, |
| 167 std::unique_ptr<KDialogOutputParams> results); |
160 | 168 |
161 // Should be either DESKTOP_ENVIRONMENT_KDE3, KDE4, or KDE5. | 169 // Should be either DESKTOP_ENVIRONMENT_KDE3, KDE4, or KDE5. |
162 base::nix::DesktopEnvironment desktop_; | 170 base::nix::DesktopEnvironment desktop_; |
163 | 171 |
164 // The set of all parent windows for which we are currently running | 172 // The set of all parent windows for which we are currently running |
165 // dialogs. This should only be accessed on the UI thread. | 173 // dialogs. This should only be accessed on the UI thread. |
166 std::set<XID> parents_; | 174 std::set<XID> parents_; |
167 | 175 |
168 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE); | 176 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE); |
169 }; | 177 }; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 filter_set.insert("application/octet-stream"); | 297 filter_set.insert("application/octet-stream"); |
290 // Create the final output string. | 298 // Create the final output string. |
291 filter_string.clear(); | 299 filter_string.clear(); |
292 for (std::set<std::string>::iterator it = filter_set.begin(); | 300 for (std::set<std::string>::iterator it = filter_set.begin(); |
293 it != filter_set.end(); ++it) { | 301 it != filter_set.end(); ++it) { |
294 filter_string.append(*it + " "); | 302 filter_string.append(*it + " "); |
295 } | 303 } |
296 return filter_string; | 304 return filter_string; |
297 } | 305 } |
298 | 306 |
299 void SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) { | 307 std::unique_ptr<SelectFileDialogImplKDE::KDialogOutputParams> |
| 308 SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) { |
300 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 309 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
301 base::CommandLine::StringVector cmd_vector; | 310 base::CommandLine::StringVector cmd_vector; |
302 cmd_vector.push_back(kKdialogBinary); | 311 cmd_vector.push_back(kKdialogBinary); |
303 base::CommandLine command_line(cmd_vector); | 312 base::CommandLine command_line(cmd_vector); |
304 GetKDialogCommandLine(params.type, params.title, params.default_path, | 313 GetKDialogCommandLine(params.type, params.title, params.default_path, |
305 params.parent, params.file_operation, | 314 params.parent, params.file_operation, |
306 params.multiple_selection, &command_line); | 315 params.multiple_selection, &command_line); |
307 std::string output; | 316 |
308 int exit_code; | 317 auto results = base::MakeUnique<KDialogOutputParams>(); |
309 // Get output from KDialog | 318 // Get output from KDialog |
310 base::GetAppOutputWithExitCode(command_line, &output, &exit_code); | 319 base::GetAppOutputWithExitCode(command_line, &results->output, |
311 if (!output.empty()) | 320 &results->exit_code); |
312 output.erase(output.size() - 1); | 321 if (!results->output.empty()) |
313 | 322 results->output.erase(results->output.size() - 1); |
314 // Now the dialog is no longer showing, but we can't erase its parent from the | 323 return results; |
315 // parent set yet because we're on the FILE thread. | |
316 BrowserThread::PostTask( | |
317 BrowserThread::UI, FROM_HERE, | |
318 base::Bind(params.callback, this, params.parent, output, exit_code, | |
319 params.kdialog_params)); | |
320 } | 324 } |
321 | 325 |
322 void SelectFileDialogImplKDE::GetKDialogCommandLine( | 326 void SelectFileDialogImplKDE::GetKDialogCommandLine( |
323 const std::string& type, | 327 const std::string& type, |
324 const std::string& title, | 328 const std::string& title, |
325 const base::FilePath& path, | 329 const base::FilePath& path, |
326 XID parent, | 330 XID parent, |
327 bool file_operation, | 331 bool file_operation, |
328 bool multiple_selection, | 332 bool multiple_selection, |
329 base::CommandLine* command_line) { | 333 base::CommandLine* command_line) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 if (listener_) | 389 if (listener_) |
386 listener_->FileSelectionCanceled(params); | 390 listener_->FileSelectionCanceled(params); |
387 } | 391 } |
388 | 392 |
389 void SelectFileDialogImplKDE::CreateSelectFolderDialog( | 393 void SelectFileDialogImplKDE::CreateSelectFolderDialog( |
390 Type type, const std::string& title, const base::FilePath& default_path, | 394 Type type, const std::string& title, const base::FilePath& default_path, |
391 XID parent, void *params) { | 395 XID parent, void *params) { |
392 int title_message_id = (type == SELECT_UPLOAD_FOLDER) | 396 int title_message_id = (type == SELECT_UPLOAD_FOLDER) |
393 ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE | 397 ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE |
394 : IDS_SELECT_FOLDER_DIALOG_TITLE; | 398 : IDS_SELECT_FOLDER_DIALOG_TITLE; |
395 BrowserThread::PostTask( | 399 BrowserThread::PostTaskAndReplyWithResult( |
396 BrowserThread::FILE, FROM_HERE, | 400 BrowserThread::FILE, FROM_HERE, |
397 base::Bind( | 401 base::Bind( |
398 &SelectFileDialogImplKDE::CallKDialogOutput, | 402 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
399 this, | |
400 KDialogParams( | 403 KDialogParams( |
401 "--getexistingdirectory", | 404 "--getexistingdirectory", GetTitle(title, title_message_id), |
402 GetTitle(title, title_message_id), | 405 default_path.empty() ? *last_opened_path_ : default_path, parent, |
403 default_path.empty() ? *last_opened_path_ : default_path, | 406 false, false)), |
404 parent, false, false, params, | 407 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse, |
405 &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse))); | 408 this, parent, params)); |
406 } | 409 } |
407 | 410 |
408 void SelectFileDialogImplKDE::CreateFileOpenDialog( | 411 void SelectFileDialogImplKDE::CreateFileOpenDialog( |
409 const std::string& title, const base::FilePath& default_path, | 412 const std::string& title, const base::FilePath& default_path, |
410 XID parent, void* params) { | 413 XID parent, void* params) { |
411 BrowserThread::PostTask( | 414 BrowserThread::PostTaskAndReplyWithResult( |
412 BrowserThread::FILE, FROM_HERE, | 415 BrowserThread::FILE, FROM_HERE, |
413 base::Bind( | 416 base::Bind( |
414 &SelectFileDialogImplKDE::CallKDialogOutput, | 417 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
415 this, | |
416 KDialogParams( | 418 KDialogParams( |
417 "--getopenfilename", | 419 "--getopenfilename", GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), |
418 GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), | 420 default_path.empty() ? *last_opened_path_ : default_path, parent, |
419 default_path.empty() ? *last_opened_path_ : default_path, | 421 true, false)), |
420 parent, true, false, params, | 422 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse, |
421 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | 423 this, parent, params)); |
422 } | 424 } |
423 | 425 |
424 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( | 426 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( |
425 const std::string& title, const base::FilePath& default_path, | 427 const std::string& title, const base::FilePath& default_path, |
426 XID parent, void* params) { | 428 XID parent, void* params) { |
427 BrowserThread::PostTask( | 429 BrowserThread::PostTaskAndReplyWithResult( |
428 BrowserThread::FILE, FROM_HERE, | 430 BrowserThread::FILE, FROM_HERE, |
429 base::Bind( | 431 base::Bind( |
430 &SelectFileDialogImplKDE::CallKDialogOutput, | 432 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
431 this, | |
432 KDialogParams( | 433 KDialogParams( |
433 "--getopenfilename", | 434 "--getopenfilename", GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), |
434 GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), | 435 default_path.empty() ? *last_opened_path_ : default_path, parent, |
435 default_path.empty() ? *last_opened_path_ : default_path, | 436 true, true)), |
436 parent, true, true, params, | 437 base::Bind(&SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse, |
437 &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse))); | 438 this, parent, params)); |
438 } | 439 } |
439 | 440 |
440 void SelectFileDialogImplKDE::CreateSaveAsDialog( | 441 void SelectFileDialogImplKDE::CreateSaveAsDialog( |
441 const std::string& title, const base::FilePath& default_path, | 442 const std::string& title, const base::FilePath& default_path, |
442 XID parent, void* params) { | 443 XID parent, void* params) { |
443 BrowserThread::PostTask( | 444 BrowserThread::PostTaskAndReplyWithResult( |
444 BrowserThread::FILE, FROM_HERE, | 445 BrowserThread::FILE, FROM_HERE, |
445 base::Bind( | 446 base::Bind( |
446 &SelectFileDialogImplKDE::CallKDialogOutput, | 447 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
447 this, | 448 KDialogParams("--getsavefilename", |
448 KDialogParams( | 449 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), |
449 "--getsavefilename", | 450 default_path.empty() ? *last_saved_path_ : default_path, |
450 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), | 451 parent, true, false)), |
451 default_path.empty() ? *last_saved_path_ : default_path, | 452 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse, |
452 parent, true, false, params, | 453 this, parent, params)); |
453 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | |
454 } | 454 } |
455 | 455 |
456 void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output, | 456 void SelectFileDialogImplKDE::SelectSingleFileHelper( |
457 int exit_code, void* params, bool allow_folder) { | 457 void* params, |
458 VLOG(1) << "[kdialog] SingleFileResponse: " << output; | 458 bool allow_folder, |
459 if (exit_code != 0 || output.empty()) { | 459 std::unique_ptr<KDialogOutputParams> results) { |
| 460 VLOG(1) << "[kdialog] SingleFileResponse: " << results->output; |
| 461 if (results->exit_code || results->output.empty()) { |
460 FileNotSelected(params); | 462 FileNotSelected(params); |
461 return; | 463 return; |
462 } | 464 } |
463 | 465 |
464 base::FilePath path(output); | 466 base::FilePath path(results->output); |
465 if (allow_folder) { | 467 if (allow_folder) { |
466 FileSelected(path, params); | 468 FileSelected(path, params); |
467 return; | 469 return; |
468 } | 470 } |
469 | 471 |
470 if (CallDirectoryExistsOnUIThread(path)) | 472 if (CallDirectoryExistsOnUIThread(path)) |
471 FileNotSelected(params); | 473 FileNotSelected(params); |
472 else | 474 else |
473 FileSelected(path, params); | 475 FileSelected(path, params); |
474 } | 476 } |
475 | 477 |
476 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( | 478 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( |
477 XID parent, const std::string& output, int exit_code, void* params) { | 479 XID parent, |
| 480 void* params, |
| 481 std::unique_ptr<KDialogOutputParams> results) { |
478 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 482 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
479 parents_.erase(parent); | 483 parents_.erase(parent); |
480 SelectSingleFileHelper(output, exit_code, params, false); | 484 SelectSingleFileHelper(params, false, std::move(results)); |
481 } | 485 } |
482 | 486 |
483 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( | 487 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( |
484 XID parent, const std::string& output, int exit_code, void* params) { | 488 XID parent, |
| 489 void* params, |
| 490 std::unique_ptr<KDialogOutputParams> results) { |
485 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 491 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
486 parents_.erase(parent); | 492 parents_.erase(parent); |
487 SelectSingleFileHelper(output, exit_code, params, true); | 493 SelectSingleFileHelper(params, true, std::move(results)); |
488 } | 494 } |
489 | 495 |
490 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( | 496 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( |
491 XID parent, const std::string& output, int exit_code, void* params) { | 497 XID parent, |
| 498 void* params, |
| 499 std::unique_ptr<KDialogOutputParams> results) { |
492 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 500 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
493 VLOG(1) << "[kdialog] MultiFileResponse: " << output; | 501 VLOG(1) << "[kdialog] MultiFileResponse: " << results->output; |
494 | 502 |
495 parents_.erase(parent); | 503 parents_.erase(parent); |
496 | 504 |
497 if (exit_code != 0 || output.empty()) { | 505 if (results->exit_code || results->output.empty()) { |
498 FileNotSelected(params); | 506 FileNotSelected(params); |
499 return; | 507 return; |
500 } | 508 } |
501 | 509 |
502 std::vector<base::FilePath> filenames_fp; | 510 std::vector<base::FilePath> filenames_fp; |
503 for (const base::StringPiece& line : | 511 for (const base::StringPiece& line : |
504 base::SplitStringPiece(output, "\n", base::KEEP_WHITESPACE, | 512 base::SplitStringPiece(results->output, "\n", base::KEEP_WHITESPACE, |
505 base::SPLIT_WANT_NONEMPTY)) { | 513 base::SPLIT_WANT_NONEMPTY)) { |
506 base::FilePath path(line); | 514 base::FilePath path(line); |
507 if (CallDirectoryExistsOnUIThread(path)) | 515 if (CallDirectoryExistsOnUIThread(path)) |
508 continue; | 516 continue; |
509 filenames_fp.push_back(path); | 517 filenames_fp.push_back(path); |
510 } | 518 } |
511 | 519 |
512 if (filenames_fp.empty()) { | 520 if (filenames_fp.empty()) { |
513 FileNotSelected(params); | 521 FileNotSelected(params); |
514 return; | 522 return; |
515 } | 523 } |
516 MultiFilesSelected(filenames_fp, params); | 524 MultiFilesSelected(filenames_fp, params); |
517 } | 525 } |
518 | 526 |
519 } // namespace libgtk2ui | 527 } // namespace libgtk2ui |
OLD | NEW |