| 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 |