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

Side by Side Diff: chrome/browser/platform_util_win.cc

Issue 2910323002: Remove old code in chrome/browser/platform_util_win.cc. (Closed)
Patch Set: Old code used NULL when it meant 0 Created 3 years, 6 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
« no previous file with comments | « no previous file | no next file » | 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/platform_util.h" 5 #include "chrome/browser/platform_util.h"
6 6
7 #include <commdlg.h> 7 #include <commdlg.h>
8 #include <dwmapi.h> 8 #include <dwmapi.h>
9 #include <shellapi.h> 9 #include <shellapi.h>
10 #include <shlobj.h> 10 #include <shlobj.h>
11 #include <stddef.h> 11 #include <stddef.h>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
16 #include "base/logging.h" 16 #include "base/logging.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/task_scheduler/post_task.h" 20 #include "base/task_scheduler/post_task.h"
21 #include "base/threading/thread_restrictions.h" 21 #include "base/threading/thread_restrictions.h"
22 #include "base/win/registry.h" 22 #include "base/win/registry.h"
23 #include "base/win/scoped_co_mem.h" 23 #include "base/win/scoped_co_mem.h"
24 #include "base/win/scoped_comptr.h" 24 #include "base/win/scoped_comptr.h"
25 #include "base/win/windows_version.h"
26 #include "chrome/browser/lifetime/application_lifetime.h"
27 #include "chrome/browser/platform_util_internal.h" 25 #include "chrome/browser/platform_util_internal.h"
28 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
29 #include "ui/base/win/shell.h" 27 #include "ui/base/win/shell.h"
30 #include "ui/gfx/native_widget_types.h" 28 #include "ui/gfx/native_widget_types.h"
31 #include "url/gurl.h" 29 #include "url/gurl.h"
32 30
33 using content::BrowserThread; 31 using content::BrowserThread;
34 32
35 namespace platform_util { 33 namespace platform_util {
36 34
37 namespace { 35 namespace {
38 36
39 void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) { 37 void ShowItemInFolderOnWorkerThread(const base::FilePath& full_path) {
40 base::ThreadRestrictions::AssertIOAllowed(); 38 base::ThreadRestrictions::AssertIOAllowed();
41 base::FilePath dir = full_path.DirName().AsEndingWithSeparator(); 39 base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
42 // ParseDisplayName will fail if the directory is "C:", it must be "C:\\". 40 // ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
43 if (dir.empty()) 41 if (dir.empty())
44 return; 42 return;
45 43
46 typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsFuncPtr)(
47 PCIDLIST_ABSOLUTE pidl_Folder,
48 UINT cidl,
49 PCUITEMID_CHILD_ARRAY pidls,
50 DWORD flags);
51
52 static SHOpenFolderAndSelectItemsFuncPtr open_folder_and_select_itemsPtr =
53 nullptr;
54 static bool initialize_open_folder_proc = true;
55 if (initialize_open_folder_proc) {
56 initialize_open_folder_proc = false;
57 // The SHOpenFolderAndSelectItems API is exposed by shell32 version 6
58 // and does not exist in Win2K. We attempt to retrieve this function export
59 // from shell32 and if it does not exist, we just invoke ShellExecute to
60 // open the folder thus losing the functionality to select the item in
61 // the process.
62 HMODULE shell32_base = GetModuleHandle(L"shell32.dll");
63 if (!shell32_base) {
64 NOTREACHED() << " " << __func__ << "(): Can't open shell32.dll";
65 return;
66 }
67 open_folder_and_select_itemsPtr =
68 reinterpret_cast<SHOpenFolderAndSelectItemsFuncPtr>
69 (GetProcAddress(shell32_base, "SHOpenFolderAndSelectItems"));
70 }
71 if (!open_folder_and_select_itemsPtr) {
72 ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
73 return;
74 }
75
76 base::win::ScopedComPtr<IShellFolder> desktop; 44 base::win::ScopedComPtr<IShellFolder> desktop;
77 HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf()); 45 HRESULT hr = SHGetDesktopFolder(desktop.GetAddressOf());
78 if (FAILED(hr)) 46 if (FAILED(hr))
79 return; 47 return;
80 48
81 base::win::ScopedCoMem<ITEMIDLIST> dir_item; 49 base::win::ScopedCoMem<ITEMIDLIST> dir_item;
82 hr = desktop->ParseDisplayName(NULL, NULL, 50 hr = desktop->ParseDisplayName(NULL, NULL,
83 const_cast<wchar_t *>(dir.value().c_str()), 51 const_cast<wchar_t *>(dir.value().c_str()),
84 NULL, &dir_item, NULL); 52 NULL, &dir_item, NULL);
85 if (FAILED(hr)) 53 if (FAILED(hr))
86 return; 54 return;
87 55
88 base::win::ScopedCoMem<ITEMIDLIST> file_item; 56 base::win::ScopedCoMem<ITEMIDLIST> file_item;
89 hr = desktop->ParseDisplayName(NULL, NULL, 57 hr = desktop->ParseDisplayName(NULL, NULL,
90 const_cast<wchar_t *>(full_path.value().c_str()), 58 const_cast<wchar_t *>(full_path.value().c_str()),
91 NULL, &file_item, NULL); 59 NULL, &file_item, NULL);
92 if (FAILED(hr)) 60 if (FAILED(hr))
93 return; 61 return;
94 62
95 const ITEMIDLIST* highlight[] = { file_item }; 63 const ITEMIDLIST* highlight[] = {file_item};
96 64
97 hr = (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight), 65 hr = SHOpenFolderAndSelectItems(dir_item, arraysize(highlight), highlight, 0);
98 highlight, NULL);
99
100 if (FAILED(hr)) { 66 if (FAILED(hr)) {
101 // On some systems, the above call mysteriously fails with "file not 67 // On some systems, the above call mysteriously fails with "file not
102 // found" even though the file is there. In these cases, ShellExecute() 68 // found" even though the file is there. In these cases, ShellExecute()
103 // seems to work as a fallback (although it won't select the file). 69 // seems to work as a fallback (although it won't select the file).
104 if (hr == ERROR_FILE_NOT_FOUND) { 70 if (hr == ERROR_FILE_NOT_FOUND) {
105 ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW); 71 ShellExecute(NULL, L"open", dir.value().c_str(), NULL, NULL, SW_SHOW);
106 } else { 72 } else {
107 LOG(WARNING) << " " << __func__ << "(): Can't open full_path = \"" 73 LOG(WARNING) << " " << __func__ << "(): Can't open full_path = \""
108 << full_path.value() << "\"" 74 << full_path.value() << "\""
109 << " hr = " << logging::SystemErrorCodeToString(hr); 75 << " hr = " << logging::SystemErrorCodeToString(hr);
110 } 76 }
111 } 77 }
112 } 78 }
113 79
114 // Old ShellExecute crashes the process when the command for a given scheme
115 // is empty. This function tells if it is.
116 bool ValidateShellCommandForScheme(const std::string& scheme) {
117 base::win::RegKey key;
118 base::string16 registry_path = base::ASCIIToUTF16(scheme) +
119 L"\\shell\\open\\command";
120 key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
121 if (!key.Valid())
122 return false;
123 DWORD size = 0;
124 key.ReadValue(NULL, NULL, &size, NULL);
125 if (size <= 2)
126 return false;
127 return true;
128 }
129
130 void OpenExternalOnWorkerThread(const GURL& url) { 80 void OpenExternalOnWorkerThread(const GURL& url) {
131 base::ThreadRestrictions::AssertIOAllowed(); 81 base::ThreadRestrictions::AssertIOAllowed();
132 // Quote the input scheme to be sure that the command does not have 82 // Quote the input scheme to be sure that the command does not have
133 // parameters unexpected by the external program. This url should already 83 // parameters unexpected by the external program. This url should already
134 // have been escaped. 84 // have been escaped.
135 std::string escaped_url = url.spec(); 85 std::string escaped_url = url.spec();
136 escaped_url.insert(0, "\""); 86 escaped_url.insert(0, "\"");
137 escaped_url += "\""; 87 escaped_url += "\"";
138 88
139 // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp: 89 // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
140 // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in 90 // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
141 // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 91 // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
142 // support URLS of 2083 chars in length, 2K is safe." 92 // support URLS of 2083 chars in length, 2K is safe."
93 //
94 // It may be possible to increase this. https://crbug.com/727909
143 const size_t kMaxUrlLength = 2048; 95 const size_t kMaxUrlLength = 2048;
144 if (escaped_url.length() > kMaxUrlLength) { 96 if (escaped_url.length() > kMaxUrlLength)
145 NOTREACHED();
146 return; 97 return;
147 }
148
149 if (base::win::GetVersion() < base::win::VERSION_WIN7) {
150 if (!ValidateShellCommandForScheme(url.scheme()))
151 return;
152 }
153 98
154 if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open", 99 if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open",
155 escaped_url.c_str(), NULL, NULL, 100 escaped_url.c_str(), NULL, NULL,
156 SW_SHOWNORMAL)) <= 32) { 101 SW_SHOWNORMAL)) <= 32) {
157 // We fail to execute the call. We could display a message to the user. 102 // On failure, it may be good to display a message to the user.
158 // TODO(nsylvain): we should also add a dialog to warn on errors. See 103 // https://crbug.com/727913
159 // bug 1136923.
160 return; 104 return;
161 } 105 }
162 } 106 }
163 107
164 } // namespace 108 } // namespace
165 109
166 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) { 110 void ShowItemInFolder(Profile* profile, const base::FilePath& full_path) {
167 PostTaskWithTraits(FROM_HERE, 111 PostTaskWithTraits(FROM_HERE,
168 {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, 112 {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
169 base::Bind(&ShowItemInFolderOnWorkerThread, full_path)); 113 base::Bind(&ShowItemInFolderOnWorkerThread, full_path));
(...skipping 17 matching lines...) Expand all
187 131
188 void OpenExternal(Profile* profile, const GURL& url) { 132 void OpenExternal(Profile* profile, const GURL& url) {
189 DCHECK_CURRENTLY_ON(BrowserThread::UI); 133 DCHECK_CURRENTLY_ON(BrowserThread::UI);
190 134
191 PostTaskWithTraits(FROM_HERE, 135 PostTaskWithTraits(FROM_HERE,
192 {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, 136 {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
193 base::Bind(&OpenExternalOnWorkerThread, url)); 137 base::Bind(&OpenExternalOnWorkerThread, url));
194 } 138 }
195 139
196 } // namespace platform_util 140 } // namespace platform_util
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698