Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: chrome/browser/views/shell_dialogs_win.cc

Issue 2893001: Clean up and simplify how we deal with filename extensions on Windows. Allow... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/shell_dialogs.h ('k') | chrome/browser/views/shell_dialogs_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <set> 12 #include <set>
13 13
14 #include "app/l10n_util.h" 14 #include "app/l10n_util.h"
15 #include "app/win_util.h" 15 #include "app/win_util.h"
16 #include "base/file_util.h" 16 #include "base/file_util.h"
17 #include "base/message_loop.h" 17 #include "base/message_loop.h"
18 #include "base/registry.h" 18 #include "base/registry.h"
19 #include "base/scoped_comptr_win.h" 19 #include "base/scoped_comptr_win.h"
20 #include "base/thread.h" 20 #include "base/thread.h"
21 #include "base/utf_string_conversions.h" 21 #include "base/utf_string_conversions.h"
22 #include "base/win_util.h" 22 #include "base/win_util.h"
23 #include "chrome/browser/chrome_thread.h" 23 #include "chrome/browser/chrome_thread.h"
24 #include "gfx/font.h" 24 #include "gfx/font.h"
25 #include "grit/app_strings.h" 25 #include "grit/app_strings.h"
26 #include "grit/generated_resources.h" 26 #include "grit/generated_resources.h"
27 #include "net/base/mime_util.h" 27 #include "net/base/mime_util.h"
28 28
29 namespace {
30
31 // This function takes the output of a SaveAs dialog: a filename, a filter and 29 // This function takes the output of a SaveAs dialog: a filename, a filter and
32 // the extension originally suggested to the user (shown in the dialog box) and 30 // the extension originally suggested to the user (shown in the dialog box) and
33 // returns back the filename with the appropriate extension tacked on. For 31 // returns back the filename with the appropriate extension tacked on. If the
34 // example, if you pass in 'foo' as filename with filter '*.jpg' this function 32 // user requests an unknown extension and is not using the 'All files' filter,
35 // will return 'foo.jpg'. It respects MIME types, so if you pass in 'foo.jpeg' 33 // the suggested extension will be appended, otherwise we will leave the
36 // with filer '*.jpg' it will return 'foo.jpeg' (will not append .jpg). 34 // filename unmodified. |filename| should contain the filename selected in the
37 // |filename| should contain the filename selected in the SaveAs dialog box and 35 // SaveAs dialog box and may include the path, |filter_selected| should be
38 // may include the path, |filter_selected| should be '*.something', for example 36 // '*.something', for example '*.*' or it can be blank (which is treated as
39 // '*.*' or it can be blank (which is treated as *.*). |suggested_ext| should 37 // *.*). |suggested_ext| should contain the extension without the dot (.) in
40 // contain the extension without the dot (.) in front, for example 'jpg'. 38 // front, for example 'jpg'.
41 std::wstring AppendExtensionIfNeeded(const std::wstring& filename, 39 std::wstring AppendExtensionIfNeeded(const std::wstring& filename,
42 const std::wstring& filter_selected, 40 const std::wstring& filter_selected,
43 const std::wstring& suggested_ext) { 41 const std::wstring& suggested_ext) {
42 DCHECK(!filename.empty());
44 std::wstring return_value = filename; 43 std::wstring return_value = filename;
45 44
46 // Get the extension the user ended up selecting. 45 // If the user didn't give us a known extension, and we wanted one, add it.
47 std::wstring selected_ext = file_util::GetFileExtensionFromPath(filename); 46 std::string selected_mime_type;
47 if (!(filter_selected.empty() || filter_selected == L"*.*") &&
48 !net::GetMimeTypeFromExtension(
49 file_util::GetFileExtensionFromPath(filename), &selected_mime_type)) {
50 if (return_value[return_value.length() - 1] != L'.')
51 return_value.append(L".");
52 return_value.append(suggested_ext);
53 }
48 54
49 if (filter_selected.empty() || filter_selected == L"*.*") { 55 // Strip any trailing dots, which Windows doesn't allow.
50 // If the user selects 'All files' we respect any extension given to us from 56 size_t index = return_value.find_last_not_of(L'.');
51 // the File Save dialog. We also strip any trailing dots, which matches 57 if (index < return_value.size() - 1)
52 // Windows Explorer and is needed because Windows doesn't allow filenames 58 return_value.resize(index + 1);
53 // to have trailing dots. The GetSaveFileName dialog will not return a
54 // string with only one or more dots.
55 size_t index = return_value.find_last_not_of(L'.');
56 if (index < return_value.size() - 1)
57 return_value.resize(index + 1);
58 } else {
59 // User selected a specific filter (not *.*) so we need to check if the
60 // extension provided has the same mime type. If it doesn't we append the
61 // extension.
62 std::string suggested_mime_type, selected_mime_type;
63 if (suggested_ext != selected_ext &&
64 (!net::GetMimeTypeFromExtension(suggested_ext, &suggested_mime_type) ||
65 !net::GetMimeTypeFromExtension(selected_ext, &selected_mime_type) ||
66 suggested_mime_type != selected_mime_type)) {
67 return_value.append(L".");
68 return_value.append(suggested_ext);
69 }
70 }
71 59
72 return return_value; 60 return return_value;
73 } 61 }
74 62
63 namespace {
64
75 // Get the file type description from the registry. This will be "Text Document" 65 // Get the file type description from the registry. This will be "Text Document"
76 // for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't 66 // for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
77 // have an entry for the file type, we return false, true if the description was 67 // have an entry for the file type, we return false, true if the description was
78 // found. 'file_ext' must be in form ".txt". 68 // found. 'file_ext' must be in form ".txt".
79 static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext, 69 static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
80 std::wstring* reg_description) { 70 std::wstring* reg_description) {
81 DCHECK(reg_description); 71 DCHECK(reg_description);
82 RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ); 72 RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
83 std::wstring reg_app; 73 std::wstring reg_app;
84 if (reg_ext.ReadValue(NULL, &reg_app) && !reg_app.empty()) { 74 if (reg_ext.ReadValue(NULL, &reg_app) && !reg_app.empty()) {
(...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) { 1116 void SelectFontDialogImpl::FontNotSelected(void* params, RunState run_state) {
1127 if (listener_) 1117 if (listener_)
1128 listener_->FontSelectionCanceled(params); 1118 listener_->FontSelectionCanceled(params);
1129 EndRun(run_state); 1119 EndRun(run_state);
1130 } 1120 }
1131 1121
1132 // static 1122 // static
1133 SelectFontDialog* SelectFontDialog::Create(Listener* listener) { 1123 SelectFontDialog* SelectFontDialog::Create(Listener* listener) {
1134 return new SelectFontDialogImpl(listener); 1124 return new SelectFontDialogImpl(listener);
1135 } 1125 }
OLDNEW
« no previous file with comments | « chrome/browser/shell_dialogs.h ('k') | chrome/browser/views/shell_dialogs_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698