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>(); |
318 std::string& output = results->output; | |
319 int& exit_code = results->exit_code; | |
309 // Get output from KDialog | 320 // Get output from KDialog |
310 base::GetAppOutputWithExitCode(command_line, &output, &exit_code); | 321 base::GetAppOutputWithExitCode(command_line, &output, &exit_code); |
Tom (Use chromium acct)
2016/08/26 18:46:23
Nit: Can we just do &results->output, &results->ex
Lei Zhang
2016/08/26 19:18:08
Done.
| |
311 if (!output.empty()) | 322 if (!output.empty()) |
312 output.erase(output.size() - 1); | 323 output.erase(output.size() - 1); |
313 | 324 return results; |
314 // Now the dialog is no longer showing, but we can't erase its parent from the | |
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 } | 325 } |
321 | 326 |
322 void SelectFileDialogImplKDE::GetKDialogCommandLine( | 327 void SelectFileDialogImplKDE::GetKDialogCommandLine( |
323 const std::string& type, | 328 const std::string& type, |
324 const std::string& title, | 329 const std::string& title, |
325 const base::FilePath& path, | 330 const base::FilePath& path, |
326 XID parent, | 331 XID parent, |
327 bool file_operation, | 332 bool file_operation, |
328 bool multiple_selection, | 333 bool multiple_selection, |
329 base::CommandLine* command_line) { | 334 base::CommandLine* command_line) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
385 if (listener_) | 390 if (listener_) |
386 listener_->FileSelectionCanceled(params); | 391 listener_->FileSelectionCanceled(params); |
387 } | 392 } |
388 | 393 |
389 void SelectFileDialogImplKDE::CreateSelectFolderDialog( | 394 void SelectFileDialogImplKDE::CreateSelectFolderDialog( |
390 Type type, const std::string& title, const base::FilePath& default_path, | 395 Type type, const std::string& title, const base::FilePath& default_path, |
391 XID parent, void *params) { | 396 XID parent, void *params) { |
392 int title_message_id = (type == SELECT_UPLOAD_FOLDER) | 397 int title_message_id = (type == SELECT_UPLOAD_FOLDER) |
393 ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE | 398 ? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE |
394 : IDS_SELECT_FOLDER_DIALOG_TITLE; | 399 : IDS_SELECT_FOLDER_DIALOG_TITLE; |
395 BrowserThread::PostTask( | 400 BrowserThread::PostTaskAndReplyWithResult( |
396 BrowserThread::FILE, FROM_HERE, | 401 BrowserThread::FILE, FROM_HERE, |
397 base::Bind( | 402 base::Bind( |
398 &SelectFileDialogImplKDE::CallKDialogOutput, | 403 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
399 this, | |
400 KDialogParams( | 404 KDialogParams( |
401 "--getexistingdirectory", | 405 "--getexistingdirectory", GetTitle(title, title_message_id), |
402 GetTitle(title, title_message_id), | 406 default_path.empty() ? *last_opened_path_ : default_path, parent, |
403 default_path.empty() ? *last_opened_path_ : default_path, | 407 false, false)), |
404 parent, false, false, params, | 408 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse, |
405 &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse))); | 409 this, parent, params)); |
406 } | 410 } |
407 | 411 |
408 void SelectFileDialogImplKDE::CreateFileOpenDialog( | 412 void SelectFileDialogImplKDE::CreateFileOpenDialog( |
409 const std::string& title, const base::FilePath& default_path, | 413 const std::string& title, const base::FilePath& default_path, |
410 XID parent, void* params) { | 414 XID parent, void* params) { |
411 BrowserThread::PostTask( | 415 BrowserThread::PostTaskAndReplyWithResult( |
412 BrowserThread::FILE, FROM_HERE, | 416 BrowserThread::FILE, FROM_HERE, |
413 base::Bind( | 417 base::Bind( |
414 &SelectFileDialogImplKDE::CallKDialogOutput, | 418 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
415 this, | |
416 KDialogParams( | 419 KDialogParams( |
417 "--getopenfilename", | 420 "--getopenfilename", GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), |
418 GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), | 421 default_path.empty() ? *last_opened_path_ : default_path, parent, |
419 default_path.empty() ? *last_opened_path_ : default_path, | 422 true, false)), |
420 parent, true, false, params, | 423 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse, |
421 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | 424 this, parent, params)); |
422 } | 425 } |
423 | 426 |
424 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( | 427 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( |
425 const std::string& title, const base::FilePath& default_path, | 428 const std::string& title, const base::FilePath& default_path, |
426 XID parent, void* params) { | 429 XID parent, void* params) { |
427 BrowserThread::PostTask( | 430 BrowserThread::PostTaskAndReplyWithResult( |
428 BrowserThread::FILE, FROM_HERE, | 431 BrowserThread::FILE, FROM_HERE, |
429 base::Bind( | 432 base::Bind( |
430 &SelectFileDialogImplKDE::CallKDialogOutput, | 433 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
431 this, | |
432 KDialogParams( | 434 KDialogParams( |
433 "--getopenfilename", | 435 "--getopenfilename", GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), |
434 GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), | 436 default_path.empty() ? *last_opened_path_ : default_path, parent, |
435 default_path.empty() ? *last_opened_path_ : default_path, | 437 true, true)), |
436 parent, true, true, params, | 438 base::Bind(&SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse, |
437 &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse))); | 439 this, parent, params)); |
438 } | 440 } |
439 | 441 |
440 void SelectFileDialogImplKDE::CreateSaveAsDialog( | 442 void SelectFileDialogImplKDE::CreateSaveAsDialog( |
441 const std::string& title, const base::FilePath& default_path, | 443 const std::string& title, const base::FilePath& default_path, |
442 XID parent, void* params) { | 444 XID parent, void* params) { |
443 BrowserThread::PostTask( | 445 BrowserThread::PostTaskAndReplyWithResult( |
444 BrowserThread::FILE, FROM_HERE, | 446 BrowserThread::FILE, FROM_HERE, |
445 base::Bind( | 447 base::Bind( |
446 &SelectFileDialogImplKDE::CallKDialogOutput, | 448 &SelectFileDialogImplKDE::CallKDialogOutput, this, |
447 this, | 449 KDialogParams("--getsavefilename", |
448 KDialogParams( | 450 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), |
449 "--getsavefilename", | 451 default_path.empty() ? *last_saved_path_ : default_path, |
450 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), | 452 parent, true, false)), |
451 default_path.empty() ? *last_saved_path_ : default_path, | 453 base::Bind(&SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse, |
452 parent, true, false, params, | 454 this, parent, params)); |
453 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | |
454 } | 455 } |
455 | 456 |
456 void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output, | 457 void SelectFileDialogImplKDE::SelectSingleFileHelper( |
457 int exit_code, void* params, bool allow_folder) { | 458 void* params, |
458 VLOG(1) << "[kdialog] SingleFileResponse: " << output; | 459 bool allow_folder, |
459 if (exit_code != 0 || output.empty()) { | 460 std::unique_ptr<KDialogOutputParams> results) { |
461 VLOG(1) << "[kdialog] SingleFileResponse: " << results->output; | |
462 if (results->exit_code || results->output.empty()) { | |
460 FileNotSelected(params); | 463 FileNotSelected(params); |
461 return; | 464 return; |
462 } | 465 } |
463 | 466 |
464 base::FilePath path(output); | 467 base::FilePath path(results->output); |
465 if (allow_folder) { | 468 if (allow_folder) { |
466 FileSelected(path, params); | 469 FileSelected(path, params); |
467 return; | 470 return; |
468 } | 471 } |
469 | 472 |
470 if (CallDirectoryExistsOnUIThread(path)) | 473 if (CallDirectoryExistsOnUIThread(path)) |
471 FileNotSelected(params); | 474 FileNotSelected(params); |
472 else | 475 else |
473 FileSelected(path, params); | 476 FileSelected(path, params); |
474 } | 477 } |
475 | 478 |
476 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( | 479 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( |
477 XID parent, const std::string& output, int exit_code, void* params) { | 480 XID parent, |
481 void* params, | |
482 std::unique_ptr<KDialogOutputParams> results) { | |
478 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 483 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
479 parents_.erase(parent); | 484 parents_.erase(parent); |
480 SelectSingleFileHelper(output, exit_code, params, false); | 485 SelectSingleFileHelper(params, false, std::move(results)); |
481 } | 486 } |
482 | 487 |
483 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( | 488 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( |
484 XID parent, const std::string& output, int exit_code, void* params) { | 489 XID parent, |
490 void* params, | |
491 std::unique_ptr<KDialogOutputParams> results) { | |
485 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 492 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
486 parents_.erase(parent); | 493 parents_.erase(parent); |
487 SelectSingleFileHelper(output, exit_code, params, true); | 494 SelectSingleFileHelper(params, true, std::move(results)); |
488 } | 495 } |
489 | 496 |
490 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( | 497 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( |
491 XID parent, const std::string& output, int exit_code, void* params) { | 498 XID parent, |
499 void* params, | |
500 std::unique_ptr<KDialogOutputParams> results) { | |
492 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 501 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
493 VLOG(1) << "[kdialog] MultiFileResponse: " << output; | 502 VLOG(1) << "[kdialog] MultiFileResponse: " << results->output; |
494 | 503 |
495 parents_.erase(parent); | 504 parents_.erase(parent); |
496 | 505 |
497 if (exit_code != 0 || output.empty()) { | 506 if (results->exit_code || results->output.empty()) { |
498 FileNotSelected(params); | 507 FileNotSelected(params); |
499 return; | 508 return; |
500 } | 509 } |
501 | 510 |
502 std::vector<base::FilePath> filenames_fp; | 511 std::vector<base::FilePath> filenames_fp; |
503 for (const base::StringPiece& line : | 512 for (const base::StringPiece& line : |
504 base::SplitStringPiece(output, "\n", base::KEEP_WHITESPACE, | 513 base::SplitStringPiece(results->output, "\n", base::KEEP_WHITESPACE, |
505 base::SPLIT_WANT_NONEMPTY)) { | 514 base::SPLIT_WANT_NONEMPTY)) { |
506 base::FilePath path(line); | 515 base::FilePath path(line); |
507 if (CallDirectoryExistsOnUIThread(path)) | 516 if (CallDirectoryExistsOnUIThread(path)) |
508 continue; | 517 continue; |
509 filenames_fp.push_back(path); | 518 filenames_fp.push_back(path); |
510 } | 519 } |
511 | 520 |
512 if (filenames_fp.empty()) { | 521 if (filenames_fp.empty()) { |
513 FileNotSelected(params); | 522 FileNotSelected(params); |
514 return; | 523 return; |
515 } | 524 } |
516 MultiFilesSelected(filenames_fp, params); | 525 MultiFilesSelected(filenames_fp, params); |
517 } | 526 } |
518 | 527 |
519 } // namespace libgtk2ui | 528 } // namespace libgtk2ui |
OLD | NEW |