OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/common/platform_util.h" | |
6 | |
7 #include <commdlg.h> | |
8 #include <dwmapi.h> | |
9 #include <shellapi.h> | |
10 #include <shlobj.h> | |
11 | |
12 #include "app/win_util.h" | |
13 #include "base/file_path.h" | |
14 #include "base/file_util.h" | |
15 #include "base/path_service.h" | |
16 #include "base/logging.h" | |
17 #include "base/registry.h" | |
18 #include "base/scoped_comptr_win.h" | |
19 #include "base/string_util.h" | |
20 #include "chrome/installer/util/google_update_settings.h" | |
21 #include "chrome/installer/util/google_update_constants.h" | |
22 #include "chrome/installer/util/install_util.h" | |
23 #include "gfx/native_widget_types.h" | |
24 #include "googleurl/src/gurl.h" | |
25 | |
26 namespace platform_util { | |
27 | |
28 void ShowItemInFolder(const FilePath& full_path) { | |
29 FilePath dir = full_path.DirName(); | |
30 // ParseDisplayName will fail if the directory is "C:", it must be "C:\\". | |
31 if (dir.value() == L"" || !file_util::EnsureEndsWithSeparator(&dir)) | |
32 return; | |
33 | |
34 typedef HRESULT (WINAPI *SHOpenFolderAndSelectItemsFuncPtr)( | |
35 PCIDLIST_ABSOLUTE pidl_Folder, | |
36 UINT cidl, | |
37 PCUITEMID_CHILD_ARRAY pidls, | |
38 DWORD flags); | |
39 | |
40 static SHOpenFolderAndSelectItemsFuncPtr open_folder_and_select_itemsPtr = | |
41 NULL; | |
42 static bool initialize_open_folder_proc = true; | |
43 if (initialize_open_folder_proc) { | |
44 initialize_open_folder_proc = false; | |
45 // The SHOpenFolderAndSelectItems API is exposed by shell32 version 6 | |
46 // and does not exist in Win2K. We attempt to retrieve this function export | |
47 // from shell32 and if it does not exist, we just invoke ShellExecute to | |
48 // open the folder thus losing the functionality to select the item in | |
49 // the process. | |
50 HMODULE shell32_base = GetModuleHandle(L"shell32.dll"); | |
51 if (!shell32_base) { | |
52 NOTREACHED(); | |
53 return; | |
54 } | |
55 open_folder_and_select_itemsPtr = | |
56 reinterpret_cast<SHOpenFolderAndSelectItemsFuncPtr> | |
57 (GetProcAddress(shell32_base, "SHOpenFolderAndSelectItems")); | |
58 } | |
59 if (!open_folder_and_select_itemsPtr) { | |
60 ShellExecute(NULL, _T("open"), dir.value().c_str(), NULL, NULL, SW_SHOW); | |
61 return; | |
62 } | |
63 | |
64 ScopedComPtr<IShellFolder> desktop; | |
65 HRESULT hr = SHGetDesktopFolder(desktop.Receive()); | |
66 if (FAILED(hr)) | |
67 return; | |
68 | |
69 win_util::CoMemReleaser<ITEMIDLIST> dir_item; | |
70 hr = desktop->ParseDisplayName(NULL, NULL, | |
71 const_cast<wchar_t *>(dir.value().c_str()), | |
72 NULL, &dir_item, NULL); | |
73 if (FAILED(hr)) | |
74 return; | |
75 | |
76 win_util::CoMemReleaser<ITEMIDLIST> file_item; | |
77 hr = desktop->ParseDisplayName(NULL, NULL, | |
78 const_cast<wchar_t *>(full_path.value().c_str()), | |
79 NULL, &file_item, NULL); | |
80 if (FAILED(hr)) | |
81 return; | |
82 | |
83 const ITEMIDLIST* highlight[] = { | |
84 {file_item}, | |
85 }; | |
86 (*open_folder_and_select_itemsPtr)(dir_item, arraysize(highlight), | |
87 highlight, NULL); | |
88 } | |
89 | |
90 void OpenItem(const FilePath& full_path) { | |
91 win_util::OpenItemViaShell(full_path); | |
92 } | |
93 | |
94 void OpenExternal(const GURL& url) { | |
95 // Quote the input scheme to be sure that the command does not have | |
96 // parameters unexpected by the external program. This url should already | |
97 // have been escaped. | |
98 std::string escaped_url = url.spec(); | |
99 escaped_url.insert(0, "\""); | |
100 escaped_url += "\""; | |
101 | |
102 // According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp: | |
103 // "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in | |
104 // ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6 | |
105 // support URLS of 2083 chars in length, 2K is safe." | |
106 const size_t kMaxUrlLength = 2048; | |
107 if (escaped_url.length() > kMaxUrlLength) { | |
108 NOTREACHED(); | |
109 return; | |
110 } | |
111 | |
112 RegKey key; | |
113 std::wstring registry_path = ASCIIToWide(url.scheme()) + | |
114 L"\\shell\\open\\command"; | |
115 key.Open(HKEY_CLASSES_ROOT, registry_path.c_str()); | |
116 if (key.Valid()) { | |
117 DWORD size = 0; | |
118 key.ReadValue(NULL, NULL, &size); | |
119 if (size <= 2) { | |
120 // ShellExecute crashes the process when the command is empty. | |
121 // We check for "2" because it always returns the trailing NULL. | |
122 // TODO(nsylvain): we should also add a dialog to warn on errors. See | |
123 // bug 1136923. | |
124 return; | |
125 } | |
126 } | |
127 | |
128 if (reinterpret_cast<ULONG_PTR>(ShellExecuteA(NULL, "open", | |
129 escaped_url.c_str(), NULL, NULL, | |
130 SW_SHOWNORMAL)) <= 32) { | |
131 // We fail to execute the call. We could display a message to the user. | |
132 // TODO(nsylvain): we should also add a dialog to warn on errors. See | |
133 // bug 1136923. | |
134 return; | |
135 } | |
136 } | |
137 | |
138 gfx::NativeWindow GetTopLevel(gfx::NativeView view) { | |
139 return GetAncestor(view, GA_ROOT); | |
140 } | |
141 | |
142 bool IsWindowActive(gfx::NativeWindow window) { | |
143 return ::GetForegroundWindow() == window; | |
144 } | |
145 | |
146 bool IsVisible(gfx::NativeView view) { | |
147 // MSVC complains if we don't include != 0. | |
148 return ::IsWindowVisible(view) != 0; | |
149 } | |
150 | |
151 void SimpleErrorBox(gfx::NativeWindow parent, | |
152 const string16& title, | |
153 const string16& message) { | |
154 win_util::MessageBox(parent, message, title, MB_OK | MB_SETFOREGROUND); | |
155 } | |
156 | |
157 string16 GetVersionStringModifier() { | |
158 #if defined(GOOGLE_CHROME_BUILD) | |
159 FilePath module; | |
160 string16 channel; | |
161 if (PathService::Get(base::FILE_MODULE, &module)) { | |
162 bool is_system_install = | |
163 !InstallUtil::IsPerUserInstall(module.value().c_str()); | |
164 | |
165 GoogleUpdateSettings::GetChromeChannel(is_system_install, &channel); | |
166 } | |
167 return channel; | |
168 #else | |
169 return string16(); | |
170 #endif | |
171 } | |
172 | |
173 } // namespace platform_util | |
OLD | NEW |