Port Android relocation packer to chromium build
[chromium-blink-merge.git] / win8 / viewer / metro_viewer_process_host.cc
blob61a776c1206d7026add3b5db40e941a926da324b
1 // Copyright (c) 2013 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.
5 #include "win8/viewer/metro_viewer_process_host.h"
7 #include <shlobj.h>
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/path_service.h"
14 #include "base/process/process.h"
15 #include "base/strings/string16.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/time/time.h"
18 #include "base/win/scoped_comptr.h"
19 #include "base/win/windows_version.h"
20 #include "ipc/ipc_channel_proxy.h"
21 #include "ipc/ipc_message.h"
22 #include "ipc/ipc_message_macros.h"
23 #include "ui/aura/remote_window_tree_host_win.h"
24 #include "ui/metro_viewer/metro_viewer_messages.h"
25 #include "win8/viewer/metro_viewer_constants.h"
27 namespace {
29 const int kViewerProcessConnectionTimeoutSecs = 60;
31 } // namespace
33 namespace win8 {
35 // static
36 MetroViewerProcessHost* MetroViewerProcessHost::instance_ = NULL;
38 MetroViewerProcessHost::InternalMessageFilter::InternalMessageFilter(
39 MetroViewerProcessHost* owner)
40 : owner_(owner) {
43 void MetroViewerProcessHost::InternalMessageFilter::OnChannelConnected(
44 int32 peer_pid) {
45 owner_->NotifyChannelConnected();
48 MetroViewerProcessHost::MetroViewerProcessHost(
49 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
50 DCHECK(!instance_);
51 instance_ = this;
53 channel_ = IPC::ChannelProxy::Create(kMetroViewerIPCChannelName,
54 IPC::Channel::MODE_NAMED_SERVER,
55 this,
56 ipc_task_runner);
59 MetroViewerProcessHost::~MetroViewerProcessHost() {
60 if (!channel_) {
61 instance_ = NULL;
62 return;
65 base::ProcessId viewer_process_id = GetViewerProcessId();
66 channel_->Close();
67 if (message_filter_.get()) {
68 // Wait for the viewer process to go away.
69 if (viewer_process_id != base::kNullProcessId) {
70 base::Process viewer_process =
71 base::Process::OpenWithAccess(
72 viewer_process_id,
73 PROCESS_QUERY_INFORMATION | SYNCHRONIZE);
74 if (viewer_process.IsValid()) {
75 int exit_code;
76 viewer_process.WaitForExit(&exit_code);
79 channel_->RemoveFilter(message_filter_.get());
81 instance_ = NULL;
84 base::ProcessId MetroViewerProcessHost::GetViewerProcessId() {
85 if (channel_)
86 return channel_->GetPeerPID();
87 return base::kNullProcessId;
90 bool MetroViewerProcessHost::LaunchViewerAndWaitForConnection(
91 const base::string16& app_user_model_id) {
92 DCHECK_EQ(base::kNullProcessId, channel_->GetPeerPID());
94 channel_connected_event_.reset(new base::WaitableEvent(false, false));
96 message_filter_ = new InternalMessageFilter(this);
97 channel_->AddFilter(message_filter_.get());
99 if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
100 base::win::ScopedComPtr<IApplicationActivationManager> activator;
101 HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager);
102 if (SUCCEEDED(hr)) {
103 DWORD pid = 0;
104 // Use the "connect" verb to
105 hr = activator->ActivateApplication(
106 app_user_model_id.c_str(), kMetroViewerConnectVerb, AO_NONE, &pid);
109 LOG_IF(ERROR, FAILED(hr)) << "Tried and failed to launch Metro Chrome. "
110 << "hr=" << std::hex << hr;
111 } else {
112 // For Windows 7 we need to launch the viewer ourselves.
113 base::FilePath chrome_path;
114 if (!PathService::Get(base::DIR_EXE, &chrome_path))
115 return false;
116 // TODO(cpu): launch with "-ServerName:DefaultBrowserServer"
117 // note that the viewer might try to launch chrome again.
118 CHECK(false);
121 // Having launched the viewer process, now we wait for it to connect.
122 bool success =
123 channel_connected_event_->TimedWait(base::TimeDelta::FromSeconds(
124 kViewerProcessConnectionTimeoutSecs));
125 channel_connected_event_.reset();
126 return success;
129 bool MetroViewerProcessHost::Send(IPC::Message* msg) {
130 return channel_->Send(msg);
133 bool MetroViewerProcessHost::OnMessageReceived(
134 const IPC::Message& message) {
135 DCHECK(CalledOnValidThread());
136 bool handled = true;
137 IPC_BEGIN_MESSAGE_MAP(MetroViewerProcessHost, message)
138 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone,
139 OnFileSaveAsDone)
140 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone,
141 OnFileOpenDone)
142 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone,
143 OnMultiFileOpenDone)
144 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_OpenURL, OnOpenURL)
145 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SearchRequest, OnHandleSearchRequest)
146 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone,
147 OnSelectFolderDone)
148 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetTargetSurface, OnSetTargetSurface)
149 IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowSizeChanged,
150 OnWindowSizeChanged)
151 IPC_MESSAGE_UNHANDLED(handled = false)
152 IPC_END_MESSAGE_MAP()
153 return handled ? true :
154 aura::RemoteWindowTreeHostWin::Instance()->OnMessageReceived(message);
157 // static
158 void MetroViewerProcessHost::HandleActivateDesktop(
159 const base::FilePath& path,
160 bool ash_exit) {
161 if (instance_) {
162 instance_->Send(
163 new MetroViewerHostMsg_ActivateDesktop(path, ash_exit));
167 // static
168 void MetroViewerProcessHost::HandleMetroExit() {
169 if (instance_)
170 instance_->Send(new MetroViewerHostMsg_MetroExit());
173 // static
174 void MetroViewerProcessHost::HandleOpenFile(
175 const base::string16& title,
176 const base::FilePath& default_path,
177 const base::string16& filter,
178 const OpenFileCompletion& on_success,
179 const FileSelectionCanceled& on_failure) {
180 if (instance_) {
181 instance_->HandleOpenFileImpl(title, default_path, filter, on_success,
182 on_failure);
186 // static
187 void MetroViewerProcessHost::HandleOpenMultipleFiles(
188 const base::string16& title,
189 const base::FilePath& default_path,
190 const base::string16& filter,
191 const OpenMultipleFilesCompletion& on_success,
192 const FileSelectionCanceled& on_failure) {
193 if (instance_) {
194 instance_->HandleOpenMultipleFilesImpl(title, default_path, filter,
195 on_success, on_failure);
199 // static
200 void MetroViewerProcessHost::HandleSaveFile(
201 const base::string16& title,
202 const base::FilePath& default_path,
203 const base::string16& filter,
204 int filter_index,
205 const base::string16& default_extension,
206 const SaveFileCompletion& on_success,
207 const FileSelectionCanceled& on_failure) {
208 if (instance_) {
209 instance_->HandleSaveFileImpl(title, default_path, filter, filter_index,
210 default_extension, on_success, on_failure);
214 // static
215 void MetroViewerProcessHost::HandleSelectFolder(
216 const base::string16& title,
217 const SelectFolderCompletion& on_success,
218 const FileSelectionCanceled& on_failure) {
219 if (instance_)
220 instance_->HandleSelectFolderImpl(title, on_success, on_failure);
223 void MetroViewerProcessHost::HandleOpenFileImpl(
224 const base::string16& title,
225 const base::FilePath& default_path,
226 const base::string16& filter,
227 const OpenFileCompletion& on_success,
228 const FileSelectionCanceled& on_failure) {
229 // Can only have one of these operations in flight.
230 DCHECK(file_open_completion_callback_.is_null());
231 DCHECK(failure_callback_.is_null());
233 file_open_completion_callback_ = on_success;
234 failure_callback_ = on_failure;
236 Send(new MetroViewerHostMsg_DisplayFileOpen(title, filter, default_path,
237 false));
240 void MetroViewerProcessHost::HandleOpenMultipleFilesImpl(
241 const base::string16& title,
242 const base::FilePath& default_path,
243 const base::string16& filter,
244 const OpenMultipleFilesCompletion& on_success,
245 const FileSelectionCanceled& on_failure) {
246 // Can only have one of these operations in flight.
247 DCHECK(multi_file_open_completion_callback_.is_null());
248 DCHECK(failure_callback_.is_null());
249 multi_file_open_completion_callback_ = on_success;
250 failure_callback_ = on_failure;
252 Send(new MetroViewerHostMsg_DisplayFileOpen(title, filter, default_path,
253 true));
256 void MetroViewerProcessHost::HandleSaveFileImpl(
257 const base::string16& title,
258 const base::FilePath& default_path,
259 const base::string16& filter,
260 int filter_index,
261 const base::string16& default_extension,
262 const SaveFileCompletion& on_success,
263 const FileSelectionCanceled& on_failure) {
264 MetroViewerHostMsg_SaveAsDialogParams params;
265 params.title = title;
266 params.default_extension = default_extension;
267 params.filter = filter;
268 params.filter_index = filter_index;
269 params.suggested_name = default_path;
271 // Can only have one of these operations in flight.
272 DCHECK(file_saveas_completion_callback_.is_null());
273 DCHECK(failure_callback_.is_null());
274 file_saveas_completion_callback_ = on_success;
275 failure_callback_ = on_failure;
277 Send(new MetroViewerHostMsg_DisplayFileSaveAs(params));
280 void MetroViewerProcessHost::HandleSelectFolderImpl(
281 const base::string16& title,
282 const SelectFolderCompletion& on_success,
283 const FileSelectionCanceled& on_failure) {
284 // Can only have one of these operations in flight.
285 DCHECK(select_folder_completion_callback_.is_null());
286 DCHECK(failure_callback_.is_null());
287 select_folder_completion_callback_ = on_success;
288 failure_callback_ = on_failure;
290 Send(new MetroViewerHostMsg_DisplaySelectFolder(title));
293 void MetroViewerProcessHost::NotifyChannelConnected() {
294 if (channel_connected_event_)
295 channel_connected_event_->Signal();
298 void MetroViewerProcessHost::OnFileSaveAsDone(bool success,
299 const base::FilePath& filename,
300 int filter_index) {
301 if (success)
302 file_saveas_completion_callback_.Run(filename, filter_index, NULL);
303 else
304 failure_callback_.Run(NULL);
305 file_saveas_completion_callback_.Reset();
306 failure_callback_.Reset();
310 void MetroViewerProcessHost::OnFileOpenDone(bool success,
311 const base::FilePath& filename) {
312 if (success)
313 file_open_completion_callback_.Run(base::FilePath(filename), 0, NULL);
314 else
315 failure_callback_.Run(NULL);
316 file_open_completion_callback_.Reset();
317 failure_callback_.Reset();
320 void MetroViewerProcessHost::OnMultiFileOpenDone(
321 bool success,
322 const std::vector<base::FilePath>& files) {
323 if (success)
324 multi_file_open_completion_callback_.Run(files, NULL);
325 else
326 failure_callback_.Run(NULL);
327 multi_file_open_completion_callback_.Reset();
328 failure_callback_.Reset();
331 void MetroViewerProcessHost::OnSelectFolderDone(
332 bool success,
333 const base::FilePath& folder) {
334 if (success)
335 select_folder_completion_callback_.Run(base::FilePath(folder), 0, NULL);
336 else
337 failure_callback_.Run(NULL);
338 select_folder_completion_callback_.Reset();
339 failure_callback_.Reset();
342 } // namespace win8