From 5bbe1597629c0b99b1dd9a80a634bd575bbb2a93 Mon Sep 17 00:00:00 2001 From: "gab@chromium.org" Date: Fri, 24 May 2013 16:55:32 +0000 Subject: Create MetroViewerProcessHost as a common base for TestMetroViewerProcessHost and ChromeMetroViewerProcessHost Bringing LaunchViewerAndWaitForConnection() to the common base so that ChromeMetroViewerProcessHost can also benefit from it (required for ash browser tests). BUG=179830 1st Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=201806 Reverted: https://src.chromium.org/viewvc/chrome?view=rev&revision=201966 R=robertshield@chromium.org, sky@chromium.org Review URL: https://codereview.chromium.org/14629025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202113 0039d316-1c4b-4281-b951-d872f2087c98 --- win8/metro_driver/metro_driver.gyp | 2 +- win8/viewer/metro_viewer_process_host.cc | 108 +++++++++++++++++++++++++++++++ win8/viewer/metro_viewer_process_host.h | 94 +++++++++++++++++++++++++++ win8/win8.gyp | 14 ++++ 4 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 win8/viewer/metro_viewer_process_host.cc create mode 100644 win8/viewer/metro_viewer_process_host.h (limited to 'win8') diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp index f1f9892..623b000 100644 --- a/win8/metro_driver/metro_driver.gyp +++ b/win8/metro_driver/metro_driver.gyp @@ -58,7 +58,7 @@ '../../google_update/google_update.gyp:google_update', '../../ipc/ipc.gyp:ipc', '../../sandbox/sandbox.gyp:sandbox', - '../../ui/metro_viewer/metro_viewer.gyp:metro_viewer', + '../../ui/metro_viewer/metro_viewer.gyp:metro_viewer_messages', '../win8.gyp:check_sdk_patch', 'metro_driver_version_resources', ], diff --git a/win8/viewer/metro_viewer_process_host.cc b/win8/viewer/metro_viewer_process_host.cc new file mode 100644 index 0000000..f945039 --- /dev/null +++ b/win8/viewer/metro_viewer_process_host.cc @@ -0,0 +1,108 @@ +// 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 + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/process.h" +#include "base/string16.h" +#include "base/synchronization/waitable_event.h" +#include "base/time.h" +#include "base/win/scoped_comptr.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_macros.h" +#include "ui/aura/remote_root_window_host_win.h" +#include "ui/metro_viewer/metro_viewer_messages.h" + +namespace win8 { + +MetroViewerProcessHost::InternalMessageFilter::InternalMessageFilter( + MetroViewerProcessHost* owner) : owner_(owner) { +} + +void MetroViewerProcessHost::InternalMessageFilter::OnChannelConnected( + int32 /* peer_pid */) { + owner_->NotifyChannelConnected(); +} + +MetroViewerProcessHost::MetroViewerProcessHost( + const std::string& ipc_channel_name, + base::SingleThreadTaskRunner* ipc_task_runner) { + + channel_.reset(new IPC::ChannelProxy( + ipc_channel_name.c_str(), + IPC::Channel::MODE_NAMED_SERVER, + this, + ipc_task_runner)); +} + +MetroViewerProcessHost::~MetroViewerProcessHost() { +} + +base::ProcessId MetroViewerProcessHost::GetViewerProcessId() { + if (channel_) + return channel_->peer_pid(); + return base::kNullProcessId; +} + +bool MetroViewerProcessHost::LaunchViewerAndWaitForConnection( + const base::string16& app_user_model_id) { + DCHECK_EQ(base::kNullProcessId, channel_->peer_pid()); + + channel_connected_event_.reset(new base::WaitableEvent(false, false)); + + scoped_refptr message_filter( + new InternalMessageFilter(this)); + channel_->AddFilter(message_filter); + + base::win::ScopedComPtr activator; + HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager); + if (SUCCEEDED(hr)) { + DWORD pid = 0; + hr = activator->ActivateApplication( + app_user_model_id.c_str(), L"open", AO_NONE, &pid); + } + + LOG_IF(ERROR, FAILED(hr)) << "Tried and failed to launch Metro Chrome. " + << "hr=" << std::hex << hr; + + // Having launched the viewer process, now we wait for it to connect. + bool success = + channel_connected_event_->TimedWait(base::TimeDelta::FromSeconds(60)); + channel_connected_event_.reset(); + + // |message_filter| is only used to signal |channel_connected_event_| above + // and can thus be removed after |channel_connected_event_| is no longer + // waiting. + channel_->RemoveFilter(message_filter); + 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_SetTargetSurface, OnSetTargetSurface) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled ? true : + aura::RemoteRootWindowHostWin::Instance()->OnMessageReceived(message); +} + +void MetroViewerProcessHost::NotifyChannelConnected() { + if (channel_connected_event_) + channel_connected_event_->Signal(); +} + +} // namespace win8 diff --git a/win8/viewer/metro_viewer_process_host.h b/win8/viewer/metro_viewer_process_host.h new file mode 100644 index 0000000..b9c3e77 --- /dev/null +++ b/win8/viewer/metro_viewer_process_host.h @@ -0,0 +1,94 @@ +// 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. + +#ifndef WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_ +#define WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_ + +#include + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/string16.h" +#include "base/threading/non_thread_safe.h" +#include "ipc/ipc_channel_proxy.h" +#include "ipc/ipc_listener.h" +#include "ipc/ipc_sender.h" +#include "ui/gfx/native_widget_types.h" + +namespace base { +class SingleThreadTaskRunner; +class WaitableEvent; +} + +namespace IPC { +class Message; +} + +namespace win8 { + +// Abstract base class for various Metro viewer process host implementations. +class MetroViewerProcessHost : public IPC::Listener, + public IPC::Sender, + public base::NonThreadSafe { + public: + // Initializes a viewer process host over |ipc_channel_name|. The given task + // runner correspond to a thread on which IPC::Channel is created and used + // (e.g. IO thread). Instantly connects to the viewer process if one is + // already connected to |ipc_channel_name|; a viewer can otherwise be + // launched synchronously via LaunchViewerAndWaitForConnection(). + MetroViewerProcessHost(const std::string& ipc_channel_name, + base::SingleThreadTaskRunner* ipc_task_runner); + virtual ~MetroViewerProcessHost(); + + // Returns the process id of the viewer process if one is connected to this + // host, returns base::kNullProcessId otherwise. + base::ProcessId GetViewerProcessId(); + + // Launches the viewer process associated with the given |app_user_model_id| + // and blocks until that viewer process connects or until a timeout is + // reached. Returns true if the viewer process connects before the timeout is + // reached. NOTE: this assumes that the app referred to by |app_user_model_id| + // is registered as the default browser. + bool LaunchViewerAndWaitForConnection( + const base::string16& app_user_model_id); + + private: + // IPC::Sender implementation: + virtual bool Send(IPC::Message* msg) OVERRIDE; + + // IPC::Listener implementation: + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + virtual void OnChannelError() OVERRIDE = 0; + + // Called over IPC by the viewer process to tell this host that it should be + // drawing to |target_surface|. + virtual void OnSetTargetSurface(gfx::NativeViewId target_surface) = 0; + + void NotifyChannelConnected(); + + // Inner message filter used to handle connection event on the IPC channel + // proxy's background thread. This prevents consumers of + // MetroViewerProcessHost from having to pump messages on their own message + // loop. + class InternalMessageFilter : public IPC::ChannelProxy::MessageFilter { + public: + InternalMessageFilter(MetroViewerProcessHost* owner); + + // IPC::ChannelProxy::MessageFilter implementation. + virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; + + private: + MetroViewerProcessHost* owner_; + DISALLOW_COPY_AND_ASSIGN(InternalMessageFilter); + }; + + scoped_ptr channel_; + scoped_ptr channel_connected_event_; + + DISALLOW_COPY_AND_ASSIGN(MetroViewerProcessHost); +}; + +} // namespace win8 + +#endif // WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_ diff --git a/win8/win8.gyp b/win8/win8.gyp index 7b198a1..6e3d5a8 100644 --- a/win8/win8.gyp +++ b/win8/win8.gyp @@ -51,6 +51,20 @@ ], }, { + 'target_name': 'metro_viewer', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../ipc/ipc.gyp:ipc', + '../ui/aura/aura.gyp:aura', + '../ui/metro_viewer/metro_viewer.gyp:metro_viewer_messages', + ], + 'sources': [ + 'viewer/metro_viewer_process_host.cc', + 'viewer/metro_viewer_process_host.h', + ], + }, + { 'target_name': 'test_support_win8', 'type': 'static_library', 'dependencies': [ -- cgit v1.1