Chromium Code Reviews| Index: win8/metro_driver/chrome_app_view_ash.cc |
| diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc |
| index db2d9f30c4e66cfdd04b7b275fae33bde260a6c4..c1b47f1378c02828a9e103f0dbf70ac3e729ee90 100644 |
| --- a/win8/metro_driver/chrome_app_view_ash.cc |
| +++ b/win8/metro_driver/chrome_app_view_ash.cc |
| @@ -14,7 +14,6 @@ |
| #include "base/files/file_path.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/path_service.h" |
| -#include "base/threading/thread.h" |
| #include "base/win/metro.h" |
| #include "base/win/win_util.h" |
| #include "base/win/windows_version.h" |
| @@ -87,6 +86,9 @@ enum KeyModifier { |
| ALT = 4 |
| }; |
| +const int kChromeChannelPollTimerMs = 100; |
| +const UINT_PTR kChromeChannelPollTimerId = 0xdeadbabe; |
| + |
| // Helper function to send keystrokes via the SendInput function. |
| // mnemonic_char: The keystroke to be sent. |
| // modifiers: Combination with Alt, Ctrl, Shift, etc. |
| @@ -273,16 +275,6 @@ class ChromeChannelListener : public IPC::Listener { |
| ChromeAppViewAsh* app_view_; |
| }; |
| -bool WaitForChromeIPCConnection(const std::string& channel_name) { |
| - int ms_elapsed = 0; |
| - while (!IPC::Channel::IsNamedServerInitialized(channel_name) && |
| - ms_elapsed < 10000) { |
| - ms_elapsed += 100; |
| - Sleep(100); |
| - } |
| - return IPC::Channel::IsNamedServerInitialized(channel_name); |
| -} |
| - |
| void RunMessageLoop(winui::Core::ICoreDispatcher* dispatcher) { |
| // We're entering a nested message loop, let's allow dispatching |
| // tasks while we're in there. |
| @@ -525,16 +517,22 @@ class ChromeAppViewAsh::PointerInfoHandler { |
| DISALLOW_COPY_AND_ASSIGN(PointerInfoHandler); |
| }; |
| +ChromeAppViewAsh* ChromeAppViewAsh::g_instance_ = NULL; |
| + |
| ChromeAppViewAsh::ChromeAppViewAsh() |
| : mouse_down_flags_(ui::EF_NONE), |
| ui_channel_(nullptr), |
| core_window_hwnd_(NULL), |
| metro_dpi_scale_(0), |
| win32_dpi_scale_(0), |
| - last_cursor_(NULL) { |
| + last_cursor_(NULL), |
| + channel_listener_(NULL) { |
| DVLOG(1) << __FUNCTION__; |
| globals.previous_state = |
| winapp::Activation::ApplicationExecutionState_NotRunning; |
| + DCHECK(!g_instance_); |
| + |
| + g_instance_ = this; |
| } |
| ChromeAppViewAsh::~ChromeAppViewAsh() { |
| @@ -678,52 +676,31 @@ ChromeAppViewAsh::Run() { |
| CheckHR(hr, "Dispatcher failed."); |
| // Create the IPC channel IO thread. It needs to out-live the ChannelProxy. |
| - base::Thread io_thread("metro_IO_thread"); |
| + io_thread_.reset(new base::Thread("metro_IO_thread")); |
| base::Thread::Options options; |
| options.message_loop_type = base::MessageLoop::TYPE_IO; |
| - io_thread.StartWithOptions(options); |
| - |
| - // Start up Chrome and wait for the desired IPC server connection to exist. |
| - WaitForChromeIPCConnection(win8::kMetroViewerIPCChannelName); |
| + io_thread_->StartWithOptions(options); |
| - // In Aura mode we create an IPC channel to the browser, then ask it to |
| - // connect to us. |
| ChromeChannelListener ui_channel_listener(&ui_loop_, this); |
| - scoped_ptr<IPC::ChannelProxy> channel = |
| - IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
| - IPC::Channel::MODE_NAMED_CLIENT, |
| - &ui_channel_listener, |
| - io_thread.message_loop_proxy()); |
| - ui_channel_ = channel.get(); |
| + channel_listener_ = &ui_channel_listener; |
| - // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the |
| - // browser will use D3D from the browser process to present to our Window. |
| - ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( |
| - gfx::NativeViewId(core_window_hwnd_), win32_dpi_scale_)); |
| - DVLOG(1) << "ICoreWindow sent " << core_window_hwnd_; |
| - |
| - // Send an initial size message so that the Ash root window host gets sized |
| - // correctly. |
| - RECT rect = {0}; |
| - ::GetWindowRect(core_window_hwnd_, &rect); |
| - ui_channel_->Send( |
| - new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
| - rect.bottom - rect.top)); |
| - |
| - input_source_ = metro_driver::InputSource::Create(); |
| - if (input_source_) { |
| - input_source_->AddObserver(this); |
| - // Send an initial input source. |
| - OnInputSourceChanged(); |
| - } |
| + // We can't do anything until the Chrome browser IPC channel is initialized. |
| + // Lazy initialization in a timer. |
| - // Start receiving IME popup window notifications. |
| - metro_driver::AddImePopupObserver(this); |
| + UINT_PTR channel_setup_timer_id = |
|
cpu_(ooo_6.6-7.5)
2014/09/25 23:00:08
change to base::timer, since in line 698 we run ou
ananta
2014/09/26 02:29:01
Good point. Done.
|
| + ::SetTimer(core_window_hwnd_, |
| + kChromeChannelPollTimerId, |
| + kChromeChannelPollTimerMs, |
| + &ChromeAppViewAsh::StartChromeOSMode); |
| - // And post the task that'll do the inner Metro message pumping to it. |
| + // Post the task that'll do the inner Metro message pumping to it. |
| ui_loop_.PostTask(FROM_HERE, base::Bind(&RunMessageLoop, dispatcher.Get())); |
| ui_loop_.Run(); |
| + io_thread_.reset(NULL); |
| + ui_channel_.reset(NULL); |
| + channel_listener_ = NULL; |
| + |
| DVLOG(0) << "ProcessEvents done, hr=" << hr; |
| return hr; |
| } |
| @@ -976,6 +953,8 @@ void ChromeAppViewAsh::OnInputSourceChanged() { |
| if (!input_source_) |
| return; |
| + DCHECK(ui_channel_); |
| + |
| LANGID langid = 0; |
| bool is_ime = false; |
| if (!input_source_->GetActiveSource(&langid, &is_ime)) { |
| @@ -1006,6 +985,8 @@ void ChromeAppViewAsh::SendMouseButton(int x, |
| uint32 flags, |
| ui::EventFlags changed_button, |
| bool is_horizontal_wheel) { |
| + if (!ui_channel_) |
| + return; |
| MetroViewerHostMsg_MouseButtonParams params; |
| params.x = static_cast<int32>(x); |
| params.y = static_cast<int32>(y); |
| @@ -1075,6 +1056,9 @@ HRESULT ChromeAppViewAsh::OnActivate( |
| HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1110,6 +1094,9 @@ HRESULT ChromeAppViewAsh::OnPointerMoved(winui::Core::ICoreWindow* sender, |
| HRESULT ChromeAppViewAsh::OnPointerPressed( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1133,6 +1120,9 @@ HRESULT ChromeAppViewAsh::OnPointerPressed( |
| HRESULT ChromeAppViewAsh::OnPointerReleased( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1158,6 +1148,9 @@ HRESULT ChromeAppViewAsh::OnPointerReleased( |
| HRESULT ChromeAppViewAsh::OnWheel( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IPointerEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| PointerInfoHandler pointer(metro_dpi_scale_, win32_dpi_scale_); |
| HRESULT hr = pointer.Init(args); |
| if (FAILED(hr)) |
| @@ -1172,6 +1165,9 @@ HRESULT ChromeAppViewAsh::OnWheel( |
| HRESULT ChromeAppViewAsh::OnKeyDown( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1191,6 +1187,9 @@ HRESULT ChromeAppViewAsh::OnKeyDown( |
| HRESULT ChromeAppViewAsh::OnKeyUp( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1210,6 +1209,9 @@ HRESULT ChromeAppViewAsh::OnKeyUp( |
| HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( |
| winui::Core::ICoreDispatcher* sender, |
| winui::Core::IAcceleratorKeyEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| winsys::VirtualKey virtual_key; |
| HRESULT hr = args->get_VirtualKey(&virtual_key); |
| if (FAILED(hr)) |
| @@ -1264,6 +1266,9 @@ HRESULT ChromeAppViewAsh::OnAcceleratorKeyDown( |
| HRESULT ChromeAppViewAsh::OnCharacterReceived( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::ICharacterReceivedEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| unsigned int char_code = 0; |
| HRESULT hr = args->get_KeyCode(&char_code); |
| if (FAILED(hr)) |
| @@ -1284,6 +1289,9 @@ HRESULT ChromeAppViewAsh::OnCharacterReceived( |
| HRESULT ChromeAppViewAsh::OnWindowActivated( |
| winui::Core::ICoreWindow* sender, |
| winui::Core::IWindowActivatedEventArgs* args) { |
| + if (!ui_channel_) |
| + return S_OK; |
| + |
| if (args) { |
| winui::Core::CoreWindowActivationState state; |
| HRESULT hr = args->get_WindowActivationState(&state); |
| @@ -1358,18 +1366,19 @@ HRESULT ChromeAppViewAsh::HandleProtocolRequest( |
| HRESULT ChromeAppViewAsh::OnEdgeGestureCompleted( |
| winui::Input::IEdgeGesture* gesture, |
| winui::Input::IEdgeGestureEventArgs* args) { |
| - ui_channel_->Send(new MetroViewerHostMsg_EdgeGesture()); |
| + if (ui_channel_) |
| + ui_channel_->Send(new MetroViewerHostMsg_EdgeGesture()); |
| return S_OK; |
| } |
| void ChromeAppViewAsh::OnSearchRequest(const base::string16& search_string) { |
| - DCHECK(ui_channel_); |
| - ui_channel_->Send(new MetroViewerHostMsg_SearchRequest(search_string)); |
| + if (ui_channel_) |
| + ui_channel_->Send(new MetroViewerHostMsg_SearchRequest(search_string)); |
| } |
| void ChromeAppViewAsh::OnNavigateToUrl(const base::string16& url) { |
| - DCHECK(ui_channel_); |
| - ui_channel_->Send(new MetroViewerHostMsg_OpenURL(url)); |
| + if (ui_channel_) |
| + ui_channel_->Send(new MetroViewerHostMsg_OpenURL(url)); |
| } |
| HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender, |
| @@ -1392,6 +1401,71 @@ HRESULT ChromeAppViewAsh::OnSizeChanged(winui::Core::ICoreWindow* sender, |
| return S_OK; |
| } |
| +// static |
| +void CALLBACK ChromeAppViewAsh::StartChromeOSMode(HWND core_window, |
| + UINT message, |
| + UINT_PTR timer_id, |
| + DWORD time) { |
| + static int ms_elapsed = 0; |
| + if (!IPC::Channel::IsNamedServerInitialized( |
| + win8::kMetroViewerIPCChannelName) && ms_elapsed < 10000) { |
| + ms_elapsed += 100; |
| + return; |
| + } |
| + |
| + ::KillTimer(core_window, kChromeChannelPollTimerId); |
| + |
| + if (!IPC::Channel::IsNamedServerInitialized( |
| + win8::kMetroViewerIPCChannelName)) { |
| + DVLOG(1) << "Failed to connect to chrome channel : " |
| + << win8::kMetroViewerIPCChannelName; |
| + DVLOG(1) << "Exiting. Elapsed time :" << ms_elapsed; |
| + PostMessage(core_window, WM_CLOSE, 0, 0); |
| + return; |
| + } |
| + |
| + DVLOG(1) << "Found channel : " << win8::kMetroViewerIPCChannelName; |
| + |
| + DCHECK(g_instance_); |
| + DCHECK(g_instance_->channel_listener_); |
| + |
| + // In Aura mode we create an IPC channel to the browser, then ask it to |
| + // connect to us. |
| + g_instance_->ui_channel_ = |
| + IPC::ChannelProxy::Create(win8::kMetroViewerIPCChannelName, |
| + IPC::Channel::MODE_NAMED_CLIENT, |
| + g_instance_->channel_listener_, |
| + g_instance_->io_thread_->message_loop_proxy()); |
| + DVLOG(1) << "Created channel proxy"; |
| + |
| + // Upon receipt of the MetroViewerHostMsg_SetTargetSurface message the |
| + // browser will use D3D from the browser process to present to our Window. |
| + g_instance_->ui_channel_->Send(new MetroViewerHostMsg_SetTargetSurface( |
| + gfx::NativeViewId(core_window), |
| + g_instance_->win32_dpi_scale_)); |
| + DVLOG(1) << "ICoreWindow sent " << core_window; |
| + |
| + // Send an initial size message so that the Ash root window host gets sized |
| + // correctly. |
| + RECT rect = {0}; |
| + ::GetWindowRect(core_window, &rect); |
| + g_instance_->ui_channel_->Send( |
| + new MetroViewerHostMsg_WindowSizeChanged(rect.right - rect.left, |
| + rect.bottom - rect.top)); |
| + |
| + g_instance_->input_source_ = metro_driver::InputSource::Create(); |
| + if (g_instance_->input_source_) { |
| + g_instance_->input_source_->AddObserver(g_instance_); |
| + // Send an initial input source. |
| + g_instance_->OnInputSourceChanged(); |
| + } |
| + |
| + // Start receiving IME popup window notifications. |
| + metro_driver::AddImePopupObserver(g_instance_); |
| + |
| + DVLOG(1) << "Channel setup complete"; |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| ChromeAppViewFactory::ChromeAppViewFactory( |