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 <set> | 5 #include <set> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/message_loop.h" |
| 12 #include "base/message_loop_proxy.h" |
11 #include "base/nix/mime_util_xdg.h" | 13 #include "base/nix/mime_util_xdg.h" |
12 #include "base/nix/xdg_util.h" | 14 #include "base/nix/xdg_util.h" |
13 #include "base/process_util.h" | 15 #include "base/process_util.h" |
14 #include "base/string_number_conversions.h" | 16 #include "base/string_number_conversions.h" |
15 #include "base/string_util.h" | 17 #include "base/string_util.h" |
16 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
| 19 #include "base/threading/worker_pool.h" |
17 #include "base/utf_string_conversions.h" | 20 #include "base/utf_string_conversions.h" |
18 #include "chrome/browser/ui/gtk/select_file_dialog_impl.h" | 21 #include "grit/ui_strings.h" |
19 | 22 #include "ui/base/dialogs/gtk/select_file_dialog_impl.h" |
20 // TODO(erg): Move all of this into WorkerPool. | |
21 #include "content/public/browser/browser_thread.h" | |
22 #include "grit/generated_resources.h" | |
23 #include "ui/base/l10n/l10n_util.h" | 23 #include "ui/base/l10n/l10n_util.h" |
24 | 24 |
25 // These conflict with base/tracked_objects.h, so need to come last. | 25 // These conflict with base/tracked_objects.h, so need to come last. |
26 #include <gdk/gdkx.h> | 26 #include <gdk/gdkx.h> |
27 #include <gtk/gtk.h> | 27 #include <gtk/gtk.h> |
28 | 28 |
29 using content::BrowserThread; | |
30 | |
31 namespace { | 29 namespace { |
32 | 30 |
33 std::string GetTitle(const std::string& title, int message_id) { | 31 std::string GetTitle(const std::string& title, int message_id) { |
34 return title.empty() ? l10n_util::GetStringUTF8(message_id) : title; | 32 return title.empty() ? l10n_util::GetStringUTF8(message_id) : title; |
35 } | 33 } |
36 | 34 |
37 const char kKdialogBinary[] = "kdialog"; | 35 const char kKdialogBinary[] = "kdialog"; |
38 | 36 |
39 } // namespace | |
40 | |
41 // Implementation of SelectFileDialog that shows a KDE common dialog for | 37 // Implementation of SelectFileDialog that shows a KDE common dialog for |
42 // choosing a file or folder. This acts as a modal dialog. | 38 // choosing a file or folder. This acts as a modal dialog. |
43 class SelectFileDialogImplKDE : public SelectFileDialogImpl { | 39 class SelectFileDialogImplKDE : public ui::SelectFileDialogImpl { |
44 public: | 40 public: |
45 SelectFileDialogImplKDE(Listener* listener, | 41 SelectFileDialogImplKDE(Listener* listener, |
46 ui::SelectFilePolicy* policy, | 42 ui::SelectFilePolicy* policy, |
47 base::nix::DesktopEnvironment desktop); | 43 base::nix::DesktopEnvironment desktop); |
48 | 44 |
49 protected: | 45 protected: |
50 virtual ~SelectFileDialogImplKDE(); | 46 virtual ~SelectFileDialogImplKDE(); |
51 | 47 |
52 // SelectFileDialog implementation. | 48 // SelectFileDialog implementation. |
53 // |params| is user data we pass back via the Listener interface. | 49 // |params| is user data we pass back via the Listener interface. |
54 virtual void SelectFileImpl(Type type, | 50 virtual void SelectFileImpl(Type type, |
55 const string16& title, | 51 const string16& title, |
56 const FilePath& default_path, | 52 const FilePath& default_path, |
57 const FileTypeInfo* file_types, | 53 const FileTypeInfo* file_types, |
58 int file_type_index, | 54 int file_type_index, |
59 const FilePath::StringType& default_extension, | 55 const FilePath::StringType& default_extension, |
60 gfx::NativeWindow owning_window, | 56 gfx::NativeWindow owning_window, |
61 void* params) OVERRIDE; | 57 void* params) OVERRIDE; |
62 | 58 |
63 private: | 59 private: |
64 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; | 60 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; |
65 | 61 |
66 struct KDialogParams { | 62 struct KDialogParams { |
| 63 // This constructor can only be run from the UI thread. |
67 KDialogParams(const std::string& type, const std::string& title, | 64 KDialogParams(const std::string& type, const std::string& title, |
68 const FilePath& default_path, gfx::NativeWindow parent, | 65 const FilePath& default_path, gfx::NativeWindow parent, |
69 bool file_operation, bool multiple_selection, | 66 bool file_operation, bool multiple_selection, |
70 void* kdialog_params, | 67 void* kdialog_params, |
71 void (SelectFileDialogImplKDE::*callback)(const std::string&, | 68 void (SelectFileDialogImplKDE::*callback)(const std::string&, |
72 int, void*)) | 69 int, void*)) |
73 : type(type), title(title), default_path(default_path), parent(parent), | 70 : type(type), title(title), default_path(default_path), parent(parent), |
74 file_operation(file_operation), | 71 file_operation(file_operation), |
75 multiple_selection(multiple_selection), | 72 multiple_selection(multiple_selection), |
76 kdialog_params(kdialog_params), callback(callback) { | 73 kdialog_params(kdialog_params), |
| 74 ui_loop_proxy(MessageLoopForUI::current()->message_loop_proxy()), |
| 75 callback(callback) { |
77 } | 76 } |
78 | 77 |
79 std::string type; | 78 std::string type; |
80 std::string title; | 79 std::string title; |
81 FilePath default_path; | 80 FilePath default_path; |
82 gfx::NativeWindow parent; | 81 gfx::NativeWindow parent; |
83 bool file_operation; | 82 bool file_operation; |
84 bool multiple_selection; | 83 bool multiple_selection; |
85 void* kdialog_params; | 84 void* kdialog_params; |
| 85 scoped_refptr<base::MessageLoopProxy> ui_loop_proxy; |
| 86 |
86 void (SelectFileDialogImplKDE::*callback)(const std::string&, int, void*); | 87 void (SelectFileDialogImplKDE::*callback)(const std::string&, int, void*); |
87 }; | 88 }; |
88 | 89 |
89 // Get the filters from |file_types_| and concatenate them into | 90 // Get the filters from |file_types_| and concatenate them into |
90 // |filter_string|. | 91 // |filter_string|. |
91 std::string GetMimeTypeFilterString(); | 92 std::string GetMimeTypeFilterString(); |
92 | 93 |
93 // Get KDialog command line representing the Argv array for KDialog. | 94 // Get KDialog command line representing the Argv array for KDialog. |
94 void GetKDialogCommandLine(const std::string& type, const std::string& title, | 95 void GetKDialogCommandLine(const std::string& type, const std::string& title, |
95 const FilePath& default_path, gfx::NativeWindow parent, | 96 const FilePath& default_path, gfx::NativeWindow parent, |
96 bool file_operation, bool multiple_selection, CommandLine* command_line); | 97 bool file_operation, bool multiple_selection, CommandLine* command_line); |
97 | 98 |
98 // Call KDialog on the FILE thread and post results back to the UI thread. | 99 // Call KDialog on a worker thread and post results back to the caller |
| 100 // thread. |
99 void CallKDialogOutput(const KDialogParams& params); | 101 void CallKDialogOutput(const KDialogParams& params); |
100 | 102 |
101 // Notifies the listener that a single file was chosen. | 103 // Notifies the listener that a single file was chosen. |
102 void FileSelected(const FilePath& path, void* params); | 104 void FileSelected(const FilePath& path, void* params); |
103 | 105 |
104 // Notifies the listener that multiple files were chosen. | 106 // Notifies the listener that multiple files were chosen. |
105 void MultiFilesSelected(const std::vector<FilePath>& files, void* params); | 107 void MultiFilesSelected(const std::vector<FilePath>& files, void* params); |
106 | 108 |
107 // Notifies the listener that no file was chosen (the action was canceled). | 109 // Notifies the listener that no file was chosen (the action was canceled). |
108 // Dialog is passed so we can find that |params| pointer that was passed to | 110 // Dialog is passed so we can find that |params| pointer that was passed to |
(...skipping 27 matching lines...) Expand all Loading... |
136 int exit_code, void* params); | 138 int exit_code, void* params); |
137 void OnSelectSingleFolderDialogResponse(const std::string& output, | 139 void OnSelectSingleFolderDialogResponse(const std::string& output, |
138 int exit_code, void* params); | 140 int exit_code, void* params); |
139 | 141 |
140 // Should be either DESKTOP_ENVIRONMENT_KDE3 or DESKTOP_ENVIRONMENT_KDE4. | 142 // Should be either DESKTOP_ENVIRONMENT_KDE3 or DESKTOP_ENVIRONMENT_KDE4. |
141 base::nix::DesktopEnvironment desktop_; | 143 base::nix::DesktopEnvironment desktop_; |
142 | 144 |
143 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE); | 145 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImplKDE); |
144 }; | 146 }; |
145 | 147 |
146 // static | |
147 bool SelectFileDialogImpl::CheckKDEDialogWorksOnUIThread() { | |
148 // No choice. UI thread can't continue without an answer here. Fortunately we | |
149 // only do this once, the first time a file dialog is displayed. | |
150 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
151 | |
152 CommandLine::StringVector cmd_vector; | |
153 cmd_vector.push_back(kKdialogBinary); | |
154 cmd_vector.push_back("--version"); | |
155 CommandLine command_line(cmd_vector); | |
156 std::string dummy; | |
157 return base::GetAppOutput(command_line, &dummy); | |
158 } | |
159 | |
160 // static | |
161 SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplKDE( | |
162 Listener* listener, | |
163 ui::SelectFilePolicy* policy, | |
164 base::nix::DesktopEnvironment desktop) { | |
165 return new SelectFileDialogImplKDE(listener, policy, desktop); | |
166 } | |
167 | |
168 SelectFileDialogImplKDE::SelectFileDialogImplKDE( | 148 SelectFileDialogImplKDE::SelectFileDialogImplKDE( |
169 Listener* listener, | 149 Listener* listener, |
170 ui::SelectFilePolicy* policy, | 150 ui::SelectFilePolicy* policy, |
171 base::nix::DesktopEnvironment desktop) | 151 base::nix::DesktopEnvironment desktop) |
172 : SelectFileDialogImpl(listener, policy), | 152 : SelectFileDialogImpl(listener, policy), |
173 desktop_(desktop) { | 153 desktop_(desktop) { |
174 DCHECK(desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 || | 154 DCHECK(desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE3 || |
175 desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE4); | 155 desktop_ == base::nix::DESKTOP_ENVIRONMENT_KDE4); |
176 } | 156 } |
177 | 157 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 NOTREACHED(); | 204 NOTREACHED(); |
225 return; | 205 return; |
226 } | 206 } |
227 } | 207 } |
228 | 208 |
229 bool SelectFileDialogImplKDE::HasMultipleFileTypeChoicesImpl() { | 209 bool SelectFileDialogImplKDE::HasMultipleFileTypeChoicesImpl() { |
230 return file_types_.extensions.size() > 1; | 210 return file_types_.extensions.size() > 1; |
231 } | 211 } |
232 | 212 |
233 std::string SelectFileDialogImplKDE::GetMimeTypeFilterString() { | 213 std::string SelectFileDialogImplKDE::GetMimeTypeFilterString() { |
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
235 std::string filter_string; | 214 std::string filter_string; |
236 // We need a filter set because the same mime type can appear multiple times. | 215 // We need a filter set because the same mime type can appear multiple times. |
237 std::set<std::string> filter_set; | 216 std::set<std::string> filter_set; |
238 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { | 217 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { |
239 for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { | 218 for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { |
240 if (!file_types_.extensions[i][j].empty()) { | 219 if (!file_types_.extensions[i][j].empty()) { |
241 std::string mime_type = base::nix::GetFileMimeType( | 220 std::string mime_type = base::nix::GetFileMimeType( |
242 FilePath("name").ReplaceExtension(file_types_.extensions[i][j])); | 221 FilePath("name").ReplaceExtension(file_types_.extensions[i][j])); |
243 filter_set.insert(mime_type); | 222 filter_set.insert(mime_type); |
244 } | 223 } |
245 } | 224 } |
246 } | 225 } |
247 // Add the *.* filter, but only if we have added other filters (otherwise it | 226 // Add the *.* filter, but only if we have added other filters (otherwise it |
248 // is implied). | 227 // is implied). |
249 if (file_types_.include_all_files && !file_types_.extensions.empty()) | 228 if (file_types_.include_all_files && !file_types_.extensions.empty()) |
250 filter_set.insert("application/octet-stream"); | 229 filter_set.insert("application/octet-stream"); |
251 // Create the final output string. | 230 // Create the final output string. |
252 filter_string.clear(); | 231 filter_string.clear(); |
253 for (std::set<std::string>::iterator it = filter_set.begin(); | 232 for (std::set<std::string>::iterator it = filter_set.begin(); |
254 it != filter_set.end(); ++it) { | 233 it != filter_set.end(); ++it) { |
255 filter_string.append(*it + " "); | 234 filter_string.append(*it + " "); |
256 } | 235 } |
257 return filter_string; | 236 return filter_string; |
258 } | 237 } |
259 | 238 |
260 void SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) { | 239 void SelectFileDialogImplKDE::CallKDialogOutput(const KDialogParams& params) { |
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
262 CommandLine::StringVector cmd_vector; | 240 CommandLine::StringVector cmd_vector; |
263 cmd_vector.push_back(kKdialogBinary); | 241 cmd_vector.push_back(kKdialogBinary); |
264 CommandLine command_line(cmd_vector); | 242 CommandLine command_line(cmd_vector); |
265 GetKDialogCommandLine(params.type, params.title, params.default_path, | 243 GetKDialogCommandLine(params.type, params.title, params.default_path, |
266 params.parent, params.file_operation, | 244 params.parent, params.file_operation, |
267 params.multiple_selection, &command_line); | 245 params.multiple_selection, &command_line); |
268 std::string output; | 246 std::string output; |
269 int exit_code; | 247 int exit_code; |
270 // Get output from KDialog | 248 // Get output from KDialog |
271 base::GetAppOutputWithExitCode(command_line, &output, &exit_code); | 249 base::GetAppOutputWithExitCode(command_line, &output, &exit_code); |
272 if (!output.empty()) | 250 if (!output.empty()) |
273 output.erase(output.size() - 1); | 251 output.erase(output.size() - 1); |
274 // Now the dialog is no longer showing. We can erase its parent from the | 252 // Now the dialog is no longer showing. We can erase its parent from the |
275 // parent set. | 253 // parent set. |
276 std::set<GtkWindow*>::iterator iter = parents_.find(params.parent); | 254 std::set<GtkWindow*>::iterator iter = parents_.find(params.parent); |
277 if (iter != parents_.end()) | 255 if (iter != parents_.end()) |
278 parents_.erase(iter); | 256 parents_.erase(iter); |
279 BrowserThread::PostTask( | 257 params.ui_loop_proxy->PostTask(FROM_HERE, |
280 BrowserThread::UI, FROM_HERE, | |
281 base::Bind(params.callback, this, output, exit_code, | 258 base::Bind(params.callback, this, output, exit_code, |
282 params.kdialog_params)); | 259 params.kdialog_params)); |
283 } | 260 } |
284 | 261 |
285 void SelectFileDialogImplKDE::GetKDialogCommandLine(const std::string& type, | 262 void SelectFileDialogImplKDE::GetKDialogCommandLine(const std::string& type, |
286 const std::string& title, const FilePath& path, | 263 const std::string& title, const FilePath& path, |
287 gfx::NativeWindow parent, bool file_operation, bool multiple_selection, | 264 gfx::NativeWindow parent, bool file_operation, bool multiple_selection, |
288 CommandLine* command_line) { | 265 CommandLine* command_line) { |
289 CHECK(command_line); | 266 CHECK(command_line); |
290 | 267 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 } | 315 } |
339 | 316 |
340 void SelectFileDialogImplKDE::FileNotSelected(void* params) { | 317 void SelectFileDialogImplKDE::FileNotSelected(void* params) { |
341 if (listener_) | 318 if (listener_) |
342 listener_->FileSelectionCanceled(params); | 319 listener_->FileSelectionCanceled(params); |
343 } | 320 } |
344 | 321 |
345 void SelectFileDialogImplKDE::CreateSelectFolderDialog( | 322 void SelectFileDialogImplKDE::CreateSelectFolderDialog( |
346 const std::string& title, const FilePath& default_path, | 323 const std::string& title, const FilePath& default_path, |
347 gfx::NativeWindow parent, void *params) { | 324 gfx::NativeWindow parent, void *params) { |
348 BrowserThread::PostTask( | 325 base::WorkerPool::PostTask(FROM_HERE, |
349 BrowserThread::FILE, FROM_HERE, | |
350 base::Bind( | 326 base::Bind( |
351 &SelectFileDialogImplKDE::CallKDialogOutput, | 327 &SelectFileDialogImplKDE::CallKDialogOutput, |
352 this, | 328 this, |
353 KDialogParams( | 329 KDialogParams( |
354 "--getexistingdirectory", | 330 "--getexistingdirectory", |
355 GetTitle(title, IDS_SELECT_FOLDER_DIALOG_TITLE), | 331 GetTitle(title, IDS_SELECT_FOLDER_DIALOG_TITLE), |
356 default_path.empty() ? *last_opened_path_ : default_path, | 332 default_path.empty() ? *last_opened_path_ : default_path, |
357 parent, false, false, params, | 333 parent, false, false, params, |
358 &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse))); | 334 &SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse)), |
| 335 true); |
359 } | 336 } |
360 | 337 |
361 void SelectFileDialogImplKDE::CreateFileOpenDialog( | 338 void SelectFileDialogImplKDE::CreateFileOpenDialog( |
362 const std::string& title, const FilePath& default_path, | 339 const std::string& title, const FilePath& default_path, |
363 gfx::NativeWindow parent, void* params) { | 340 gfx::NativeWindow parent, void* params) { |
364 BrowserThread::PostTask( | 341 base::WorkerPool::PostTask(FROM_HERE, |
365 BrowserThread::FILE, FROM_HERE, | |
366 base::Bind( | 342 base::Bind( |
367 &SelectFileDialogImplKDE::CallKDialogOutput, | 343 &SelectFileDialogImplKDE::CallKDialogOutput, |
368 this, | 344 this, |
369 KDialogParams( | 345 KDialogParams( |
370 "--getopenfilename", | 346 "--getopenfilename", |
371 GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), | 347 GetTitle(title, IDS_OPEN_FILE_DIALOG_TITLE), |
372 default_path.empty() ? *last_opened_path_ : default_path, | 348 default_path.empty() ? *last_opened_path_ : default_path, |
373 parent, true, false, params, | 349 parent, true, false, params, |
374 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | 350 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)), |
| 351 true); |
375 } | 352 } |
376 | 353 |
377 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( | 354 void SelectFileDialogImplKDE::CreateMultiFileOpenDialog( |
378 const std::string& title, const FilePath& default_path, | 355 const std::string& title, const FilePath& default_path, |
379 gfx::NativeWindow parent, void* params) { | 356 gfx::NativeWindow parent, void* params) { |
380 BrowserThread::PostTask( | 357 base::WorkerPool::PostTask(FROM_HERE, |
381 BrowserThread::FILE, FROM_HERE, | |
382 base::Bind( | 358 base::Bind( |
383 &SelectFileDialogImplKDE::CallKDialogOutput, | 359 &SelectFileDialogImplKDE::CallKDialogOutput, |
384 this, | 360 this, |
385 KDialogParams( | 361 KDialogParams( |
386 "--getopenfilename", | 362 "--getopenfilename", |
387 GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), | 363 GetTitle(title, IDS_OPEN_FILES_DIALOG_TITLE), |
388 default_path.empty() ? *last_opened_path_ : default_path, | 364 default_path.empty() ? *last_opened_path_ : default_path, |
389 parent, true, true, params, | 365 parent, true, true, params, |
390 &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse))); | 366 &SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse)), |
| 367 true); |
391 } | 368 } |
392 | 369 |
393 void SelectFileDialogImplKDE::CreateSaveAsDialog( | 370 void SelectFileDialogImplKDE::CreateSaveAsDialog( |
394 const std::string& title, const FilePath& default_path, | 371 const std::string& title, const FilePath& default_path, |
395 gfx::NativeWindow parent, void* params) { | 372 gfx::NativeWindow parent, void* params) { |
396 BrowserThread::PostTask( | 373 base::WorkerPool::PostTask(FROM_HERE, |
397 BrowserThread::FILE, FROM_HERE, | |
398 base::Bind( | 374 base::Bind( |
399 &SelectFileDialogImplKDE::CallKDialogOutput, | 375 &SelectFileDialogImplKDE::CallKDialogOutput, |
400 this, | 376 this, |
401 KDialogParams( | 377 KDialogParams( |
402 "--getsavefilename", | 378 "--getsavefilename", |
403 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), | 379 GetTitle(title, IDS_SAVE_AS_DIALOG_TITLE), |
404 default_path.empty() ? *last_saved_path_ : default_path, | 380 default_path.empty() ? *last_saved_path_ : default_path, |
405 parent, true, false, params, | 381 parent, true, false, params, |
406 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse))); | 382 &SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse)), |
| 383 true); |
407 } | 384 } |
408 | 385 |
409 void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output, | 386 void SelectFileDialogImplKDE::SelectSingleFileHelper(const std::string& output, |
410 int exit_code, void* params, bool allow_folder) { | 387 int exit_code, void* params, bool allow_folder) { |
411 VLOG(1) << "[kdialog] SingleFileResponse: " << output; | 388 VLOG(1) << "[kdialog] SingleFileResponse: " << output; |
412 if (exit_code != 0 || output.empty()) { | 389 if (exit_code != 0 || output.empty()) { |
413 FileNotSelected(params); | 390 FileNotSelected(params); |
414 return; | 391 return; |
415 } | 392 } |
416 | 393 |
417 FilePath path(output); | 394 FilePath path(output); |
418 if (allow_folder) { | 395 if (allow_folder) { |
419 FileSelected(path, params); | 396 FileSelected(path, params); |
420 return; | 397 return; |
421 } | 398 } |
422 | 399 |
423 if (CallDirectoryExistsOnUIThread(path)) | 400 if (CallDirectoryExistsOnUIThread(path)) |
424 FileNotSelected(params); | 401 FileNotSelected(params); |
425 else | 402 else |
426 FileSelected(path, params); | 403 FileSelected(path, params); |
427 } | 404 } |
428 | 405 |
429 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( | 406 void SelectFileDialogImplKDE::OnSelectSingleFileDialogResponse( |
430 const std::string& output, int exit_code, void* params) { | 407 const std::string& output, int exit_code, void* params) { |
431 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
432 SelectSingleFileHelper(output, exit_code, params, false); | 408 SelectSingleFileHelper(output, exit_code, params, false); |
433 } | 409 } |
434 | 410 |
435 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( | 411 void SelectFileDialogImplKDE::OnSelectSingleFolderDialogResponse( |
436 const std::string& output, int exit_code, void* params) { | 412 const std::string& output, int exit_code, void* params) { |
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
438 SelectSingleFileHelper(output, exit_code, params, true); | 413 SelectSingleFileHelper(output, exit_code, params, true); |
439 } | 414 } |
440 | 415 |
441 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( | 416 void SelectFileDialogImplKDE::OnSelectMultiFileDialogResponse( |
442 const std::string& output, int exit_code, void* params) { | 417 const std::string& output, int exit_code, void* params) { |
443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
444 VLOG(1) << "[kdialog] MultiFileResponse: " << output; | 418 VLOG(1) << "[kdialog] MultiFileResponse: " << output; |
445 | 419 |
446 if (exit_code != 0 || output.empty()) { | 420 if (exit_code != 0 || output.empty()) { |
447 FileNotSelected(params); | 421 FileNotSelected(params); |
448 return; | 422 return; |
449 } | 423 } |
450 | 424 |
451 std::vector<std::string> filenames; | 425 std::vector<std::string> filenames; |
452 Tokenize(output, "\n", &filenames); | 426 Tokenize(output, "\n", &filenames); |
453 std::vector<FilePath> filenames_fp; | 427 std::vector<FilePath> filenames_fp; |
454 for (std::vector<std::string>::iterator iter = filenames.begin(); | 428 for (std::vector<std::string>::iterator iter = filenames.begin(); |
455 iter != filenames.end(); ++iter) { | 429 iter != filenames.end(); ++iter) { |
456 FilePath path(*iter); | 430 FilePath path(*iter); |
457 if (CallDirectoryExistsOnUIThread(path)) | 431 if (CallDirectoryExistsOnUIThread(path)) |
458 continue; | 432 continue; |
459 filenames_fp.push_back(path); | 433 filenames_fp.push_back(path); |
460 } | 434 } |
461 | 435 |
462 if (filenames_fp.empty()) { | 436 if (filenames_fp.empty()) { |
463 FileNotSelected(params); | 437 FileNotSelected(params); |
464 return; | 438 return; |
465 } | 439 } |
466 MultiFilesSelected(filenames_fp, params); | 440 MultiFilesSelected(filenames_fp, params); |
467 } | 441 } |
| 442 |
| 443 } // namespace |
| 444 |
| 445 namespace ui { |
| 446 |
| 447 // static |
| 448 bool SelectFileDialogImpl::CheckKDEDialogWorksOnUIThread() { |
| 449 // No choice. UI thread can't continue without an answer here. Fortunately we |
| 450 // only do this once, the first time a file dialog is displayed. |
| 451 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 452 |
| 453 CommandLine::StringVector cmd_vector; |
| 454 cmd_vector.push_back(kKdialogBinary); |
| 455 cmd_vector.push_back("--version"); |
| 456 CommandLine command_line(cmd_vector); |
| 457 std::string dummy; |
| 458 return base::GetAppOutput(command_line, &dummy); |
| 459 } |
| 460 |
| 461 // static |
| 462 SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplKDE( |
| 463 Listener* listener, |
| 464 ui::SelectFilePolicy* policy, |
| 465 base::nix::DesktopEnvironment desktop) { |
| 466 return new SelectFileDialogImplKDE(listener, policy, desktop); |
| 467 } |
| 468 |
| 469 } // namespace ui |
| 470 |
OLD | NEW |