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

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

Issue 2098713003: Moved a bunch of win-specific files to the new win folder in chrome/browser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 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
OLDNEW
(Empty)
1 // Copyright 2014 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/browser/chrome_select_file_dialog_factory_win.h"
6
7 #include <Windows.h>
8 #include <commdlg.h>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/strings/string16.h"
18 #include "base/synchronization/waitable_event.h"
19 #include "chrome/common/chrome_utility_messages.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "content/public/browser/utility_process_host.h"
22 #include "content/public/browser/utility_process_host_client.h"
23 #include "ipc/ipc_message_macros.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/win/open_file_name_win.h"
26 #include "ui/shell_dialogs/select_file_dialog_win.h"
27
28 namespace {
29
30 bool ShouldIsolateShellOperations() {
31 return base::FieldTrialList::FindFullName("IsolateShellOperations") ==
32 "Enabled";
33 }
34
35 // Receives the GetOpenFileName result from the utility process.
36 class GetOpenFileNameClient : public content::UtilityProcessHostClient {
37 public:
38 GetOpenFileNameClient();
39
40 // Blocks until the GetOpenFileName result is received (including failure to
41 // launch or a crash of the utility process).
42 void WaitForCompletion();
43
44 // Returns the selected directory.
45 const base::FilePath& directory() const { return directory_; }
46
47 // Returns the list of selected filenames. Each should be interpreted as a
48 // child of directory().
49 const std::vector<base::FilePath>& filenames() const { return filenames_; }
50
51 // UtilityProcessHostClient implementation
52 void OnProcessCrashed(int exit_code) override;
53 void OnProcessLaunchFailed(int error_code) override;
54 bool OnMessageReceived(const IPC::Message& message) override;
55
56 protected:
57 ~GetOpenFileNameClient() override;
58
59 private:
60 void OnResult(const base::FilePath& directory,
61 const std::vector<base::FilePath>& filenames);
62 void OnFailure();
63
64 base::FilePath directory_;
65 std::vector<base::FilePath> filenames_;
66 base::WaitableEvent event_;
67
68 DISALLOW_COPY_AND_ASSIGN(GetOpenFileNameClient);
69 };
70
71 GetOpenFileNameClient::GetOpenFileNameClient()
72 : event_(base::WaitableEvent::ResetPolicy::MANUAL,
73 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
74
75 void GetOpenFileNameClient::WaitForCompletion() {
76 event_.Wait();
77 }
78
79 void GetOpenFileNameClient::OnProcessCrashed(int exit_code) {
80 event_.Signal();
81 }
82
83 void GetOpenFileNameClient::OnProcessLaunchFailed(int error_code) {
84 event_.Signal();
85 }
86
87 bool GetOpenFileNameClient::OnMessageReceived(const IPC::Message& message) {
88 bool handled = true;
89 IPC_BEGIN_MESSAGE_MAP(GetOpenFileNameClient, message)
90 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetOpenFileName_Failed,
91 OnFailure)
92 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetOpenFileName_Result,
93 OnResult)
94 IPC_MESSAGE_UNHANDLED(handled = false)
95 IPC_END_MESSAGE_MAP()
96 return handled;
97 }
98
99 GetOpenFileNameClient::~GetOpenFileNameClient() {}
100
101 void GetOpenFileNameClient::OnResult(
102 const base::FilePath& directory,
103 const std::vector<base::FilePath>& filenames) {
104 directory_ = directory;
105 filenames_ = filenames;
106 event_.Signal();
107 }
108
109 void GetOpenFileNameClient::OnFailure() {
110 event_.Signal();
111 }
112
113 // Initiates IPC with a new utility process using |client|. Instructs the
114 // utility process to call GetOpenFileName with |ofn|. |current_task_runner|
115 // must be the currently executing task runner.
116 void DoInvokeGetOpenFileName(
117 OPENFILENAME* ofn,
118 scoped_refptr<GetOpenFileNameClient> client,
119 const scoped_refptr<base::SequencedTaskRunner>& current_task_runner) {
120 DCHECK(current_task_runner->RunsTasksOnCurrentThread());
121
122 base::WeakPtr<content::UtilityProcessHost> utility_process_host(
123 content::UtilityProcessHost::Create(client, current_task_runner)
124 ->AsWeakPtr());
125 utility_process_host->SetName(l10n_util::GetStringUTF16(
126 IDS_UTILITY_PROCESS_FILE_DIALOG_NAME));
127 utility_process_host->DisableSandbox();
128 utility_process_host->Send(new ChromeUtilityMsg_GetOpenFileName(
129 ofn->hwndOwner,
130 ofn->Flags & ~OFN_ENABLEHOOK, // We can't send a hook function over IPC.
131 ui::win::OpenFileName::GetFilters(ofn),
132 base::FilePath(ofn->lpstrInitialDir ? ofn->lpstrInitialDir
133 : base::string16()),
134 base::FilePath(ofn->lpstrFile)));
135 }
136
137 // Invokes GetOpenFileName in a utility process. Blocks until the result is
138 // received. Uses |blocking_task_runner| for IPC.
139 bool GetOpenFileNameInUtilityProcess(
140 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
141 OPENFILENAME* ofn) {
142 scoped_refptr<GetOpenFileNameClient> client(new GetOpenFileNameClient);
143 blocking_task_runner->PostTask(
144 FROM_HERE,
145 base::Bind(&DoInvokeGetOpenFileName,
146 base::Unretained(ofn), client, blocking_task_runner));
147 client->WaitForCompletion();
148
149 if (!client->filenames().size())
150 return false;
151
152 ui::win::OpenFileName::SetResult(
153 client->directory(), client->filenames(), ofn);
154 return true;
155 }
156
157 // Implements GetOpenFileName for CreateWinSelectFileDialog by delegating to a
158 // utility process.
159 bool GetOpenFileNameImpl(
160 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
161 OPENFILENAME* ofn) {
162 if (ShouldIsolateShellOperations())
163 return GetOpenFileNameInUtilityProcess(blocking_task_runner, ofn);
164
165 return ::GetOpenFileName(ofn) == TRUE;
166 }
167
168 class GetSaveFileNameClient : public content::UtilityProcessHostClient {
169 public:
170 GetSaveFileNameClient();
171
172 // Blocks until the GetSaveFileName result is received (including failure to
173 // launch or a crash of the utility process).
174 void WaitForCompletion();
175
176 // Returns the selected path.
177 const base::FilePath& path() const { return path_; }
178
179 // Returns the index of the user-selected filter.
180 int one_based_filter_index() const { return one_based_filter_index_; }
181
182 // UtilityProcessHostClient implementation
183 void OnProcessCrashed(int exit_code) override;
184 void OnProcessLaunchFailed(int error_code) override;
185 bool OnMessageReceived(const IPC::Message& message) override;
186
187 protected:
188 ~GetSaveFileNameClient() override;
189
190 private:
191 void OnResult(const base::FilePath& path, int one_based_filter_index);
192 void OnFailure();
193
194 base::FilePath path_;
195 int one_based_filter_index_;
196 base::WaitableEvent event_;
197
198 DISALLOW_COPY_AND_ASSIGN(GetSaveFileNameClient);
199 };
200
201 GetSaveFileNameClient::GetSaveFileNameClient()
202 : one_based_filter_index_(0),
203 event_(base::WaitableEvent::ResetPolicy::MANUAL,
204 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
205
206 void GetSaveFileNameClient::WaitForCompletion() {
207 event_.Wait();
208 }
209
210 void GetSaveFileNameClient::OnProcessCrashed(int exit_code) {
211 event_.Signal();
212 }
213
214 void GetSaveFileNameClient::OnProcessLaunchFailed(int error_code) {
215 event_.Signal();
216 }
217
218 bool GetSaveFileNameClient::OnMessageReceived(const IPC::Message& message) {
219 bool handled = true;
220 IPC_BEGIN_MESSAGE_MAP(GetSaveFileNameClient, message)
221 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetSaveFileName_Failed,
222 OnFailure)
223 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_GetSaveFileName_Result,
224 OnResult)
225 IPC_MESSAGE_UNHANDLED(handled = false)
226 IPC_END_MESSAGE_MAP()
227 return handled;
228 }
229
230 GetSaveFileNameClient::~GetSaveFileNameClient() {}
231
232 void GetSaveFileNameClient::OnResult(const base::FilePath& path,
233 int one_based_filter_index) {
234 path_ = path;
235 one_based_filter_index_ = one_based_filter_index;
236 event_.Signal();
237 }
238
239 void GetSaveFileNameClient::OnFailure() {
240 event_.Signal();
241 }
242
243 // Initiates IPC with a new utility process using |client|. Instructs the
244 // utility process to call GetSaveFileName with |ofn|. |current_task_runner|
245 // must be the currently executing task runner.
246 void DoInvokeGetSaveFileName(
247 OPENFILENAME* ofn,
248 scoped_refptr<GetSaveFileNameClient> client,
249 const scoped_refptr<base::SequencedTaskRunner>& current_task_runner) {
250 DCHECK(current_task_runner->RunsTasksOnCurrentThread());
251
252 base::WeakPtr<content::UtilityProcessHost> utility_process_host(
253 content::UtilityProcessHost::Create(client, current_task_runner)
254 ->AsWeakPtr());
255 utility_process_host->SetName(l10n_util::GetStringUTF16(
256 IDS_UTILITY_PROCESS_FILE_DIALOG_NAME));
257 utility_process_host->DisableSandbox();
258 ChromeUtilityMsg_GetSaveFileName_Params params;
259 params.owner = ofn->hwndOwner;
260 // We can't pass the hook function over IPC.
261 params.flags = ofn->Flags & ~OFN_ENABLEHOOK;
262 params.filters = ui::win::OpenFileName::GetFilters(ofn);
263 params.one_based_filter_index = ofn->nFilterIndex;
264 params.suggested_filename = base::FilePath(ofn->lpstrFile);
265 params.initial_directory = base::FilePath(
266 ofn->lpstrInitialDir ? ofn->lpstrInitialDir : base::string16());
267 params.default_extension =
268 ofn->lpstrDefExt ? base::string16(ofn->lpstrDefExt) : base::string16();
269
270 utility_process_host->Send(new ChromeUtilityMsg_GetSaveFileName(params));
271 }
272
273 // Invokes GetSaveFileName in a utility process. Blocks until the result is
274 // received. Uses |blocking_task_runner| for IPC.
275 bool GetSaveFileNameInUtilityProcess(
276 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
277 OPENFILENAME* ofn) {
278 scoped_refptr<GetSaveFileNameClient> client(new GetSaveFileNameClient);
279 blocking_task_runner->PostTask(
280 FROM_HERE,
281 base::Bind(&DoInvokeGetSaveFileName,
282 base::Unretained(ofn), client, blocking_task_runner));
283 client->WaitForCompletion();
284
285 if (client->path().empty())
286 return false;
287
288 base::wcslcpy(ofn->lpstrFile, client->path().value().c_str(), ofn->nMaxFile);
289 ofn->nFilterIndex = client->one_based_filter_index();
290
291 return true;
292 }
293
294 // Implements GetSaveFileName for CreateWinSelectFileDialog by delegating to a
295 // utility process.
296 bool GetSaveFileNameImpl(
297 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
298 OPENFILENAME* ofn) {
299 if (ShouldIsolateShellOperations())
300 return GetSaveFileNameInUtilityProcess(blocking_task_runner, ofn);
301
302 return ::GetSaveFileName(ofn) == TRUE;
303 }
304
305 } // namespace
306
307 ChromeSelectFileDialogFactory::ChromeSelectFileDialogFactory(
308 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
309 : blocking_task_runner_(blocking_task_runner) {
310 }
311
312 ChromeSelectFileDialogFactory::~ChromeSelectFileDialogFactory() {}
313
314 ui::SelectFileDialog* ChromeSelectFileDialogFactory::Create(
315 ui::SelectFileDialog::Listener* listener,
316 ui::SelectFilePolicy* policy) {
317 return ui::CreateWinSelectFileDialog(
318 listener,
319 policy,
320 base::Bind(GetOpenFileNameImpl, blocking_task_runner_),
321 base::Bind(GetSaveFileNameImpl, blocking_task_runner_));
322 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_select_file_dialog_factory_win.h ('k') | chrome/browser/diagnostics/recon_diagnostics.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698