| Index: win8/viewer/metro_viewer_process_host.cc
|
| diff --git a/win8/viewer/metro_viewer_process_host.cc b/win8/viewer/metro_viewer_process_host.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a3652410d413a25cefa04ab0e7af970f16f593af
|
| --- /dev/null
|
| +++ b/win8/viewer/metro_viewer_process_host.cc
|
| @@ -0,0 +1,346 @@
|
| +// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "win8/viewer/metro_viewer_process_host.h"
|
| +
|
| +#include <shlobj.h>
|
| +#include <stdint.h>
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/files/file_path.h"
|
| +#include "base/files/file_util.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/path_service.h"
|
| +#include "base/process/process.h"
|
| +#include "base/strings/string16.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| +#include "base/time/time.h"
|
| +#include "base/win/scoped_comptr.h"
|
| +#include "base/win/windows_version.h"
|
| +#include "ipc/ipc_channel_proxy.h"
|
| +#include "ipc/ipc_message.h"
|
| +#include "ipc/ipc_message_macros.h"
|
| +#include "ui/aura/remote_window_tree_host_win.h"
|
| +#include "ui/metro_viewer/metro_viewer_messages.h"
|
| +#include "win8/viewer/metro_viewer_constants.h"
|
| +
|
| +namespace {
|
| +
|
| +const int kViewerProcessConnectionTimeoutSecs = 60;
|
| +
|
| +} // namespace
|
| +
|
| +namespace win8 {
|
| +
|
| +// static
|
| +MetroViewerProcessHost* MetroViewerProcessHost::instance_ = NULL;
|
| +
|
| +MetroViewerProcessHost::InternalMessageFilter::InternalMessageFilter(
|
| + MetroViewerProcessHost* owner)
|
| + : owner_(owner) {
|
| +}
|
| +
|
| +void MetroViewerProcessHost::InternalMessageFilter::OnChannelConnected(
|
| + int32_t peer_pid) {
|
| + owner_->NotifyChannelConnected();
|
| +}
|
| +
|
| +MetroViewerProcessHost::InternalMessageFilter::~InternalMessageFilter() {
|
| +}
|
| +
|
| +MetroViewerProcessHost::MetroViewerProcessHost(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
|
| + DCHECK(!instance_);
|
| + instance_ = this;
|
| +
|
| + channel_ = IPC::ChannelProxy::Create(kMetroViewerIPCChannelName,
|
| + IPC::Channel::MODE_NAMED_SERVER,
|
| + this,
|
| + ipc_task_runner);
|
| +}
|
| +
|
| +MetroViewerProcessHost::~MetroViewerProcessHost() {
|
| + if (!channel_) {
|
| + instance_ = NULL;
|
| + return;
|
| + }
|
| +
|
| + base::ProcessId viewer_process_id = GetViewerProcessId();
|
| + channel_->Close();
|
| + if (message_filter_.get()) {
|
| + // Wait for the viewer process to go away.
|
| + if (viewer_process_id != base::kNullProcessId) {
|
| + base::Process viewer_process =
|
| + base::Process::OpenWithAccess(
|
| + viewer_process_id,
|
| + PROCESS_QUERY_INFORMATION | SYNCHRONIZE);
|
| + if (viewer_process.IsValid()) {
|
| + int exit_code;
|
| + viewer_process.WaitForExit(&exit_code);
|
| + }
|
| + }
|
| + channel_->RemoveFilter(message_filter_.get());
|
| + }
|
| + instance_ = NULL;
|
| +}
|
| +
|
| +base::ProcessId MetroViewerProcessHost::GetViewerProcessId() {
|
| + if (channel_)
|
| + return channel_->GetPeerPID();
|
| + return base::kNullProcessId;
|
| +}
|
| +
|
| +bool MetroViewerProcessHost::LaunchViewerAndWaitForConnection(
|
| + const base::string16& app_user_model_id) {
|
| + DCHECK_EQ(base::kNullProcessId, channel_->GetPeerPID());
|
| +
|
| + channel_connected_event_.reset(new base::WaitableEvent(false, false));
|
| +
|
| + message_filter_ = new InternalMessageFilter(this);
|
| + channel_->AddFilter(message_filter_.get());
|
| +
|
| + if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
|
| + base::win::ScopedComPtr<IApplicationActivationManager> activator;
|
| + HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager);
|
| + if (SUCCEEDED(hr)) {
|
| + DWORD pid = 0;
|
| + // Use the "connect" verb to
|
| + hr = activator->ActivateApplication(
|
| + app_user_model_id.c_str(), kMetroViewerConnectVerb, AO_NONE, &pid);
|
| + }
|
| +
|
| + LOG_IF(ERROR, FAILED(hr)) << "Tried and failed to launch Metro Chrome. "
|
| + << "hr=" << std::hex << hr;
|
| + } else {
|
| + // For Windows 7 we need to launch the viewer ourselves.
|
| + base::FilePath chrome_path;
|
| + if (!PathService::Get(base::DIR_EXE, &chrome_path))
|
| + return false;
|
| + // TODO(cpu): launch with "-ServerName:DefaultBrowserServer"
|
| + // note that the viewer might try to launch chrome again.
|
| + CHECK(false);
|
| + }
|
| +
|
| + // Having launched the viewer process, now we wait for it to connect.
|
| + bool success =
|
| + channel_connected_event_->TimedWait(base::TimeDelta::FromSeconds(
|
| + kViewerProcessConnectionTimeoutSecs));
|
| + channel_connected_event_.reset();
|
| + return success;
|
| +}
|
| +
|
| +bool MetroViewerProcessHost::Send(IPC::Message* msg) {
|
| + return channel_->Send(msg);
|
| +}
|
| +
|
| +bool MetroViewerProcessHost::OnMessageReceived(
|
| + const IPC::Message& message) {
|
| + DCHECK(CalledOnValidThread());
|
| + bool handled = true;
|
| + IPC_BEGIN_MESSAGE_MAP(MetroViewerProcessHost, message)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileSaveAsDone,
|
| + OnFileSaveAsDone)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_FileOpenDone,
|
| + OnFileOpenDone)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_MultiFileOpenDone,
|
| + OnMultiFileOpenDone)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_OpenURL, OnOpenURL)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SearchRequest, OnHandleSearchRequest)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SelectFolderDone,
|
| + OnSelectFolderDone)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_SetTargetSurface, OnSetTargetSurface)
|
| + IPC_MESSAGE_HANDLER(MetroViewerHostMsg_WindowSizeChanged,
|
| + OnWindowSizeChanged)
|
| + IPC_MESSAGE_UNHANDLED(handled = false)
|
| + IPC_END_MESSAGE_MAP()
|
| + return handled ? true :
|
| + aura::RemoteWindowTreeHostWin::Instance()->OnMessageReceived(message);
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleActivateDesktop(
|
| + const base::FilePath& path,
|
| + bool ash_exit) {
|
| + if (instance_) {
|
| + instance_->Send(
|
| + new MetroViewerHostMsg_ActivateDesktop(path, ash_exit));
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleMetroExit() {
|
| + if (instance_)
|
| + instance_->Send(new MetroViewerHostMsg_MetroExit());
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleOpenFile(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + const OpenFileCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + if (instance_) {
|
| + instance_->HandleOpenFileImpl(title, default_path, filter, on_success,
|
| + on_failure);
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleOpenMultipleFiles(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + const OpenMultipleFilesCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + if (instance_) {
|
| + instance_->HandleOpenMultipleFilesImpl(title, default_path, filter,
|
| + on_success, on_failure);
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleSaveFile(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + int filter_index,
|
| + const base::string16& default_extension,
|
| + const SaveFileCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + if (instance_) {
|
| + instance_->HandleSaveFileImpl(title, default_path, filter, filter_index,
|
| + default_extension, on_success, on_failure);
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void MetroViewerProcessHost::HandleSelectFolder(
|
| + const base::string16& title,
|
| + const SelectFolderCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + if (instance_)
|
| + instance_->HandleSelectFolderImpl(title, on_success, on_failure);
|
| +}
|
| +
|
| +void MetroViewerProcessHost::HandleOpenFileImpl(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + const OpenFileCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + // Can only have one of these operations in flight.
|
| + DCHECK(file_open_completion_callback_.is_null());
|
| + DCHECK(failure_callback_.is_null());
|
| +
|
| + file_open_completion_callback_ = on_success;
|
| + failure_callback_ = on_failure;
|
| +
|
| + Send(new MetroViewerHostMsg_DisplayFileOpen(title, filter, default_path,
|
| + false));
|
| +}
|
| +
|
| +void MetroViewerProcessHost::HandleOpenMultipleFilesImpl(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + const OpenMultipleFilesCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + // Can only have one of these operations in flight.
|
| + DCHECK(multi_file_open_completion_callback_.is_null());
|
| + DCHECK(failure_callback_.is_null());
|
| + multi_file_open_completion_callback_ = on_success;
|
| + failure_callback_ = on_failure;
|
| +
|
| + Send(new MetroViewerHostMsg_DisplayFileOpen(title, filter, default_path,
|
| + true));
|
| +}
|
| +
|
| +void MetroViewerProcessHost::HandleSaveFileImpl(
|
| + const base::string16& title,
|
| + const base::FilePath& default_path,
|
| + const base::string16& filter,
|
| + int filter_index,
|
| + const base::string16& default_extension,
|
| + const SaveFileCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + MetroViewerHostMsg_SaveAsDialogParams params;
|
| + params.title = title;
|
| + params.default_extension = default_extension;
|
| + params.filter = filter;
|
| + params.filter_index = filter_index;
|
| + params.suggested_name = default_path;
|
| +
|
| + // Can only have one of these operations in flight.
|
| + DCHECK(file_saveas_completion_callback_.is_null());
|
| + DCHECK(failure_callback_.is_null());
|
| + file_saveas_completion_callback_ = on_success;
|
| + failure_callback_ = on_failure;
|
| +
|
| + Send(new MetroViewerHostMsg_DisplayFileSaveAs(params));
|
| +}
|
| +
|
| +void MetroViewerProcessHost::HandleSelectFolderImpl(
|
| + const base::string16& title,
|
| + const SelectFolderCompletion& on_success,
|
| + const FileSelectionCanceled& on_failure) {
|
| + // Can only have one of these operations in flight.
|
| + DCHECK(select_folder_completion_callback_.is_null());
|
| + DCHECK(failure_callback_.is_null());
|
| + select_folder_completion_callback_ = on_success;
|
| + failure_callback_ = on_failure;
|
| +
|
| + Send(new MetroViewerHostMsg_DisplaySelectFolder(title));
|
| +}
|
| +
|
| +void MetroViewerProcessHost::NotifyChannelConnected() {
|
| + if (channel_connected_event_)
|
| + channel_connected_event_->Signal();
|
| +}
|
| +
|
| +void MetroViewerProcessHost::OnFileSaveAsDone(bool success,
|
| + const base::FilePath& filename,
|
| + int filter_index) {
|
| + if (success)
|
| + file_saveas_completion_callback_.Run(filename, filter_index, NULL);
|
| + else
|
| + failure_callback_.Run(NULL);
|
| + file_saveas_completion_callback_.Reset();
|
| + failure_callback_.Reset();
|
| +}
|
| +
|
| +
|
| +void MetroViewerProcessHost::OnFileOpenDone(bool success,
|
| + const base::FilePath& filename) {
|
| + if (success)
|
| + file_open_completion_callback_.Run(base::FilePath(filename), 0, NULL);
|
| + else
|
| + failure_callback_.Run(NULL);
|
| + file_open_completion_callback_.Reset();
|
| + failure_callback_.Reset();
|
| +}
|
| +
|
| +void MetroViewerProcessHost::OnMultiFileOpenDone(
|
| + bool success,
|
| + const std::vector<base::FilePath>& files) {
|
| + if (success)
|
| + multi_file_open_completion_callback_.Run(files, NULL);
|
| + else
|
| + failure_callback_.Run(NULL);
|
| + multi_file_open_completion_callback_.Reset();
|
| + failure_callback_.Reset();
|
| +}
|
| +
|
| +void MetroViewerProcessHost::OnSelectFolderDone(
|
| + bool success,
|
| + const base::FilePath& folder) {
|
| + if (success)
|
| + select_folder_completion_callback_.Run(base::FilePath(folder), 0, NULL);
|
| + else
|
| + failure_callback_.Run(NULL);
|
| + select_folder_completion_callback_.Reset();
|
| + failure_callback_.Reset();
|
| +}
|
| +
|
| +} // namespace win8
|
|
|