OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/shell_dialogs.h" | 5 #include "chrome/browser/shell_dialogs.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <commdlg.h> | 8 #include <commdlg.h> |
9 #include <shlobj.h> | 9 #include <shlobj.h> |
10 #include <atlbase.h> | 10 #include <atlbase.h> |
11 | 11 |
12 #include <algorithm> | 12 #include <algorithm> |
13 #include <set> | 13 #include <set> |
14 | 14 |
15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
16 #include "base/registry.h" | 16 #include "base/registry.h" |
17 #include "base/string_util.h" | 17 #include "base/string_util.h" |
18 #include "base/thread.h" | 18 #include "base/thread.h" |
19 #include "chrome/browser/browser_process.h" | 19 #include "chrome/browser/browser_process.h" |
20 #include "chrome/common/gfx/chrome_font.h" | 20 #include "chrome/common/gfx/chrome_font.h" |
21 #include "chrome/common/l10n_util.h" | 21 #include "chrome/common/l10n_util.h" |
22 #include "chrome/common/win_util.h" | 22 #include "chrome/common/win_util.h" |
23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
24 | 24 |
| 25 // Helpers to show certain types of Windows shell dialogs in a way that doesn't |
| 26 // block the UI of the entire app. |
| 27 |
25 class ShellDialogThread : public base::Thread { | 28 class ShellDialogThread : public base::Thread { |
26 public: | 29 public: |
27 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } | 30 ShellDialogThread() : base::Thread("Chrome_ShellDialogThread") { } |
28 | 31 |
29 protected: | 32 protected: |
30 void Init() { | 33 void Init() { |
31 // Initializes the COM library on the current thread. | 34 // Initializes the COM library on the current thread. |
32 CoInitialize(NULL); | 35 CoInitialize(NULL); |
33 } | 36 } |
34 | 37 |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 | 188 |
186 // Implementation of SelectFileDialog that shows a Windows common dialog for | 189 // Implementation of SelectFileDialog that shows a Windows common dialog for |
187 // choosing a file or folder. | 190 // choosing a file or folder. |
188 class SelectFileDialogImpl : public SelectFileDialog, | 191 class SelectFileDialogImpl : public SelectFileDialog, |
189 public BaseShellDialogImpl { | 192 public BaseShellDialogImpl { |
190 public: | 193 public: |
191 explicit SelectFileDialogImpl(Listener* listener); | 194 explicit SelectFileDialogImpl(Listener* listener); |
192 virtual ~SelectFileDialogImpl(); | 195 virtual ~SelectFileDialogImpl(); |
193 | 196 |
194 // SelectFileDialog implementation: | 197 // SelectFileDialog implementation: |
195 virtual void SelectFile(Type type, const string16& title, | 198 virtual void SelectFile(Type type, |
| 199 const string16& title, |
196 const FilePath& default_path, | 200 const FilePath& default_path, |
197 const std::wstring& filter, | 201 const FileTypeInfo* file_types, |
198 int filter_index, | 202 int file_type_index, |
199 const FilePath::StringType& default_extension, | 203 const FilePath::StringType& default_extension, |
200 HWND owning_hwnd, | 204 gfx::NativeWindow owning_window, |
201 void* params); | 205 void* params); |
202 virtual bool IsRunning(HWND owning_hwnd) const; | 206 virtual bool IsRunning(HWND owning_hwnd) const; |
203 virtual void ListenerDestroyed(); | 207 virtual void ListenerDestroyed(); |
204 | 208 |
205 private: | 209 private: |
206 // A struct for holding all the state necessary for displaying a Save dialog. | 210 // A struct for holding all the state necessary for displaying a Save dialog. |
207 struct ExecuteSelectParams { | 211 struct ExecuteSelectParams { |
208 ExecuteSelectParams(Type type, | 212 ExecuteSelectParams(Type type, |
209 const std::wstring& title, | 213 const std::wstring& title, |
210 const FilePath& default_path, | 214 const FilePath& default_path, |
211 const std::wstring& filter, | 215 const FileTypeInfo* file_types, |
212 int filter_index, | 216 int file_type_index, |
213 const std::wstring& default_extension, | 217 const std::wstring& default_extension, |
214 RunState run_state, | 218 RunState run_state, |
215 HWND owner, | 219 HWND owner, |
216 void* params) | 220 void* params) |
217 : type(type), title(title), default_path(default_path), filter(filter), | 221 : type(type), |
218 filter_index(filter_index), default_extension(default_extension), | 222 title(title), |
219 run_state(run_state), owner(owner), params(params) { | 223 default_path(default_path), |
| 224 file_type_index(file_type_index), |
| 225 default_extension(default_extension), |
| 226 run_state(run_state), |
| 227 owner(owner), |
| 228 params(params) { |
| 229 if (file_types) { |
| 230 this->file_types = *file_types; |
| 231 } else { |
| 232 this->file_types.include_all_files = true; |
| 233 } |
220 } | 234 } |
221 SelectFileDialog::Type type; | 235 SelectFileDialog::Type type; |
222 std::wstring title; | 236 std::wstring title; |
223 FilePath default_path; | 237 FilePath default_path; |
224 std::wstring filter; | 238 FileTypeInfo file_types; |
225 int filter_index; | 239 int file_type_index; |
226 std::wstring default_extension; | 240 std::wstring default_extension; |
227 RunState run_state; | 241 RunState run_state; |
228 HWND owner; | 242 HWND owner; |
229 void* params; | 243 void* params; |
230 }; | 244 }; |
231 | 245 |
232 // Shows the file selection dialog modal to |owner| and calls the result | 246 // Shows the file selection dialog modal to |owner| and calls the result |
233 // back on the ui thread. Run on the dialog thread. | 247 // back on the ui thread. Run on the dialog thread. |
234 void ExecuteSelectFile(const ExecuteSelectParams& params); | 248 void ExecuteSelectFile(const ExecuteSelectParams& params); |
235 | 249 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 BaseShellDialogImpl() { | 298 BaseShellDialogImpl() { |
285 } | 299 } |
286 | 300 |
287 SelectFileDialogImpl::~SelectFileDialogImpl() { | 301 SelectFileDialogImpl::~SelectFileDialogImpl() { |
288 } | 302 } |
289 | 303 |
290 void SelectFileDialogImpl::SelectFile( | 304 void SelectFileDialogImpl::SelectFile( |
291 Type type, | 305 Type type, |
292 const string16& title, | 306 const string16& title, |
293 const FilePath& default_path, | 307 const FilePath& default_path, |
294 const std::wstring& filter, | 308 const FileTypeInfo* file_types, |
295 int filter_index, | 309 int file_type_index, |
296 const FilePath::StringType& default_extension, | 310 const FilePath::StringType& default_extension, |
297 HWND owner, | 311 gfx::NativeWindow owning_window, |
298 void* params) { | 312 void* params) { |
299 ExecuteSelectParams execute_params(type, UTF16ToWide(title), default_path, | 313 ExecuteSelectParams execute_params(type, UTF16ToWide(title), default_path, |
300 filter, filter_index, default_extension, | 314 file_types, file_type_index, |
301 BeginRun(owner), owner, params); | 315 default_extension, BeginRun(owning_window), |
| 316 owning_window, params); |
302 execute_params.run_state.dialog_thread->message_loop()->PostTask(FROM_HERE, | 317 execute_params.run_state.dialog_thread->message_loop()->PostTask(FROM_HERE, |
303 NewRunnableMethod(this, &SelectFileDialogImpl::ExecuteSelectFile, | 318 NewRunnableMethod(this, &SelectFileDialogImpl::ExecuteSelectFile, |
304 execute_params)); | 319 execute_params)); |
305 } | 320 } |
306 | 321 |
307 bool SelectFileDialogImpl::IsRunning(HWND owning_hwnd) const { | 322 bool SelectFileDialogImpl::IsRunning(HWND owning_hwnd) const { |
308 return listener_ && IsRunningDialogForOwner(owning_hwnd); | 323 return listener_ && IsRunningDialogForOwner(owning_hwnd); |
309 } | 324 } |
310 | 325 |
311 void SelectFileDialogImpl::ListenerDestroyed() { | 326 void SelectFileDialogImpl::ListenerDestroyed() { |
312 // Our associated listener has gone away, so we shouldn't call back to it if | 327 // Our associated listener has gone away, so we shouldn't call back to it if |
313 // our worker thread returns after the listener is dead. | 328 // our worker thread returns after the listener is dead. |
314 listener_ = NULL; | 329 listener_ = NULL; |
315 } | 330 } |
316 | 331 |
317 void SelectFileDialogImpl::ExecuteSelectFile( | 332 void SelectFileDialogImpl::ExecuteSelectFile( |
318 const ExecuteSelectParams& params) { | 333 const ExecuteSelectParams& params) { |
| 334 std::vector<std::wstring> exts; |
| 335 for (size_t i=0; i<params.file_types.extensions.size(); ++i) { |
| 336 const std::vector<std::wstring>& inner_exts = |
| 337 params.file_types.extensions[i]; |
| 338 std::wstring ext_string; |
| 339 for (size_t j=0; j<inner_exts.size(); ++j) { |
| 340 if (!ext_string.empty()) |
| 341 ext_string.push_back(L';'); |
| 342 ext_string.push_back(L'.'); |
| 343 ext_string.append(inner_exts[j]); |
| 344 } |
| 345 exts.push_back(ext_string); |
| 346 } |
| 347 std::wstring filter = win_util::FormatFilterForExtensions( |
| 348 exts, |
| 349 params.file_types.extension_description_overrides, |
| 350 params.file_types.include_all_files); |
| 351 |
319 FilePath path = params.default_path; | 352 FilePath path = params.default_path; |
320 bool success = false; | 353 bool success = false; |
321 unsigned filter_index = params.filter_index; | 354 unsigned filter_index = params.file_type_index; |
322 if (params.type == SELECT_FOLDER) { | 355 if (params.type == SELECT_FOLDER) { |
323 success = RunSelectFolderDialog(params.title, | 356 success = RunSelectFolderDialog(params.title, |
324 params.run_state.owner, | 357 params.run_state.owner, |
325 &path); | 358 &path); |
326 } else if (params.type == SELECT_SAVEAS_FILE) { | 359 } else if (params.type == SELECT_SAVEAS_FILE) { |
327 std::wstring path_as_wstring = path.ToWStringHack(); | 360 std::wstring path_as_wstring = path.ToWStringHack(); |
328 success = win_util::SaveFileAsWithFilter(params.run_state.owner, | 361 success = win_util::SaveFileAsWithFilter(params.run_state.owner, |
329 params.default_path.ToWStringHack(), params.filter, | 362 params.default_path.ToWStringHack(), filter, |
330 params.default_extension, false, &filter_index, &path_as_wstring); | 363 params.default_extension, false, &filter_index, &path_as_wstring); |
331 if(success) { | 364 if(success) { |
332 path = FilePath::FromWStringHack(path_as_wstring); | 365 path = FilePath::FromWStringHack(path_as_wstring); |
333 } | 366 } |
334 DisableOwner(params.run_state.owner); | 367 DisableOwner(params.run_state.owner); |
335 } else if (params.type == SELECT_OPEN_FILE) { | 368 } else if (params.type == SELECT_OPEN_FILE) { |
336 success = RunOpenFileDialog(params.title, params.filter, | 369 success = RunOpenFileDialog(params.title, filter, |
337 params.run_state.owner, &path); | 370 params.run_state.owner, &path); |
338 } else if (params.type == SELECT_OPEN_MULTI_FILE) { | 371 } else if (params.type == SELECT_OPEN_MULTI_FILE) { |
339 std::vector<FilePath> paths; | 372 std::vector<FilePath> paths; |
340 if (RunOpenMultiFileDialog(params.title, params.filter, | 373 if (RunOpenMultiFileDialog(params.title, filter, |
341 params.run_state.owner, &paths)) { | 374 params.run_state.owner, &paths)) { |
342 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 375 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, |
343 &SelectFileDialogImpl::MultiFilesSelected, | 376 &SelectFileDialogImpl::MultiFilesSelected, |
344 paths, params.params, params.run_state)); | 377 paths, params.params, params.run_state)); |
345 return; | 378 return; |
346 } | 379 } |
347 } | 380 } |
348 | 381 |
349 if (success) { | 382 if (success) { |
350 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 383 ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 DisableOwner(owner); | 451 DisableOwner(owner); |
419 if (list) { | 452 if (list) { |
420 STRRET out_dir_buffer; | 453 STRRET out_dir_buffer; |
421 ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer)); | 454 ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer)); |
422 out_dir_buffer.uType = STRRET_WSTR; | 455 out_dir_buffer.uType = STRRET_WSTR; |
423 CComPtr<IShellFolder> shell_folder = NULL; | 456 CComPtr<IShellFolder> shell_folder = NULL; |
424 if (SHGetDesktopFolder (&shell_folder) == NOERROR) { | 457 if (SHGetDesktopFolder (&shell_folder) == NOERROR) { |
425 HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING, | 458 HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING, |
426 &out_dir_buffer); | 459 &out_dir_buffer); |
427 if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) { | 460 if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) { |
428 *path = FilePath::FromWStringHack(out_dir_buffer.pOleStr); | 461 *path = FilePath(out_dir_buffer.pOleStr); |
429 CoTaskMemFree(out_dir_buffer.pOleStr); | 462 CoTaskMemFree(out_dir_buffer.pOleStr); |
430 result = true; | 463 result = true; |
431 } | 464 } |
432 else { | 465 else { |
433 // Use old way if we don't get what we want. | 466 // Use old way if we don't get what we want. |
434 wchar_t old_out_dir_buffer[MAX_PATH + 1]; | 467 wchar_t old_out_dir_buffer[MAX_PATH + 1]; |
435 if (SHGetPathFromIDList(list, old_out_dir_buffer)) { | 468 if (SHGetPathFromIDList(list, old_out_dir_buffer)) { |
436 *path = FilePath::FromWStringHack(old_out_dir_buffer); | 469 *path = FilePath(old_out_dir_buffer); |
437 result = true; | 470 result = true; |
438 } | 471 } |
439 } | 472 } |
440 | 473 |
441 // According to MSDN, win2000 will not resolve shortcuts, so we do it | 474 // According to MSDN, win2000 will not resolve shortcuts, so we do it |
442 // ourself. | 475 // ourself. |
443 file_util::ResolveShortcut(path); | 476 file_util::ResolveShortcut(path); |
444 } | 477 } |
445 CoTaskMemFree(list); | 478 CoTaskMemFree(list); |
446 } | 479 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { | 724 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { |
692 if (listener_) | 725 if (listener_) |
693 listener_->FontSelectionCanceled(params); | 726 listener_->FontSelectionCanceled(params); |
694 EndRun(run_state); | 727 EndRun(run_state); |
695 } | 728 } |
696 | 729 |
697 // static | 730 // static |
698 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { | 731 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { |
699 return new SelectFontDialogImpl(listener); | 732 return new SelectFontDialogImpl(listener); |
700 } | 733 } |
OLD | NEW |