Chromium Code Reviews| Index: chrome/browser/ui/views/external_tab_container_win.cc |
| diff --git a/chrome/browser/ui/views/external_tab_container_win.cc b/chrome/browser/ui/views/external_tab_container_win.cc |
| index 6bb6eceb3fb945eefb85fc3223b5de909d8fbe0c..b9da5c44e835121418fddea9c60c95344a915536 100644 |
| --- a/chrome/browser/ui/views/external_tab_container_win.cc |
| +++ b/chrome/browser/ui/views/external_tab_container_win.cc |
| @@ -4,6 +4,10 @@ |
| #include "chrome/browser/ui/views/external_tab_container_win.h" |
| +#include <atlbase.h> |
| +#include <atlapp.h> |
| +#include <atlconv.h> |
| +#include <atlmisc.h> |
| #include <string> |
| #include "base/bind.h" |
| @@ -51,6 +55,7 @@ |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_view.h" |
| #include "content/public/common/bindings_policy.h" |
| #include "content/public/common/frame_navigate_params.h" |
| #include "content/public/common/page_transition_types.h" |
| @@ -69,7 +74,12 @@ |
| #include "ui/base/view_prop.h" |
| #include "ui/views/controls/webview/webview.h" |
| #include "ui/views/layout/grid_layout.h" |
| -#include "ui/views/win/hwnd_message_handler.h" |
| +#include "ui/views/widget/widget.h" |
| + |
| +#if defined(USE_AURA) |
| +#include "ui/aura/root_window.h" |
| +#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h" |
| +#endif |
| using content::BrowserThread; |
| using content::LoadNotificationDetails; |
| @@ -80,15 +90,97 @@ using content::OpenURLParams; |
| using content::RenderViewHost; |
| using content::SSLStatus; |
| using content::WebContents; |
| -using ui::ViewProp; |
| using WebKit::WebCString; |
| using WebKit::WebReferrerPolicy; |
| using WebKit::WebSecurityPolicy; |
| using WebKit::WebString; |
| +namespace { |
| + |
| static const char kWindowObjectKey[] = "ChromeWindowObject"; |
| -namespace { |
| +// The following helper functions exist to localize UI toolkik-specific code. |
| + |
| +HWND HWNDFromNativeView(gfx::NativeView native_view) { |
| +#if defined(USE_AURA) |
|
sky
2013/02/26 17:15:29
Use c/b/ui/views/hwnd_util.h
grt (UTC plus 2)
2013/02/27 16:53:11
Awesome! Done.
|
| + if (!native_view) |
| + return NULL; |
| + aura::RootWindow* root_window = native_view->GetRootWindow(); |
| + if (!root_window) |
| + return NULL; |
| + return root_window->GetAcceleratedWidget(); |
| +#else |
| + return native_view; |
| +#endif |
| +} |
| + |
| +void ShowNativeView(gfx::NativeView view) { |
| +#if !defined(USE_AURA) |
| + ::ShowWindow(view, SW_SHOWNA); |
| +#endif |
| +} |
| + |
| +scoped_ptr<content::NativeWebKeyboardEvent> CreateKeyboardEvent( |
| + const MSG& msg) { |
| +#if defined(USE_AURA) |
| + // TODO(grt): confirm that this is a translated character event. |
| + ui::KeyEvent key_event(msg, true); |
| + return scoped_ptr<content::NativeWebKeyboardEvent>( |
| + new content::NativeWebKeyboardEvent(&key_event)); |
| +#else |
| + return scoped_ptr<content::NativeWebKeyboardEvent>( |
| + new content::NativeWebKeyboardEvent(msg)); |
| +#endif |
| +} |
| + |
| +const MSG& MessageFromKeyboardEvent( |
| + const content::NativeWebKeyboardEvent& event) { |
| +#if defined(USE_AURA) |
| + return event.os_event->native_event(); |
| +#else |
| + return event.os_event; |
| +#endif |
| +} |
| + |
| +// A Widget class that notifies a WidgetLifecycleDelegate when it experiences |
| +// lifecycle events. |
| +class FilteringWidget : public views::Widget { |
|
sky
2013/02/26 17:15:29
Move the methods you care about onto WidgetObserve
grt (UTC plus 2)
2013/02/27 16:53:11
Done. I haven't yet found any existing WidgetObser
|
| + public: |
| + explicit FilteringWidget(WidgetLifecycleDelegate* delegate); |
| + virtual ~FilteringWidget(); |
| + |
| + protected: |
| + // views::internal::NativeWidgetDelegate methods. |
| + virtual void OnNativeWidgetCreated() OVERRIDE; |
| + virtual void OnNativeWidgetDestroying() OVERRIDE; |
| + virtual void OnNativeWidgetDestroyed() OVERRIDE; |
| + |
| + private: |
| + WidgetLifecycleDelegate* delegate_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(FilteringWidget); |
| +}; |
| + |
| +FilteringWidget::FilteringWidget( |
| + WidgetLifecycleDelegate* delegate) |
| + : delegate_(delegate) {} |
| + |
| +FilteringWidget::~FilteringWidget() {} |
| + |
| +void FilteringWidget::OnNativeWidgetCreated() { |
| + views::Widget::OnNativeWidgetCreated(); |
| + delegate_->OnNativeWidgetCreated(); |
| +} |
| + |
| +void FilteringWidget::OnNativeWidgetDestroying() { |
| + delegate_->OnNativeWidgetDestroying(); |
| + views::Widget::OnNativeWidgetDestroying(); |
| +} |
| + |
| +void FilteringWidget::OnNativeWidgetDestroyed() { |
| + views::Widget::OnNativeWidgetDestroyed(); |
| + delegate_->OnNativeWidgetDestroyed(); |
| +} |
| // Convert ui::MenuModel into a serializable form for Chrome Frame |
| ContextMenuModel* ConvertMenuModel(const ui::MenuModel* ui_model) { |
| @@ -122,7 +214,7 @@ base::LazyInstance<ExternalTabContainerWin::PendingTabs> |
| ExternalTabContainerWin::ExternalTabContainerWin( |
| AutomationProvider* automation, |
| AutomationResourceMessageFilter* filter) |
| - : views::NativeWidgetWin(new views::Widget), |
| + : widget_(NULL), |
| automation_(automation), |
| tab_contents_container_(NULL), |
| tab_handle_(0), |
| @@ -166,29 +258,32 @@ bool ExternalTabContainerWin::Init(Profile* profile, |
| const GURL& referrer, |
| bool infobars_enabled, |
| bool route_all_top_level_navigations) { |
| - if (IsWindow(GetNativeView())) { |
| + if (widget_) { |
| NOTREACHED(); |
| return false; |
| } |
| + widget_ = new FilteringWidget(this); |
| load_requests_via_automation_ = load_requests_via_automation; |
| handle_top_level_requests_ = handle_top_level_requests; |
| route_all_top_level_navigations_ = route_all_top_level_navigations; |
|
sky
2013/02/26 17:15:29
See this in the member initializer list too.
grt (UTC plus 2)
2013/02/27 16:53:11
Done.
|
| - GetMessageHandler()->set_window_style(WS_POPUP | WS_CLIPCHILDREN); |
| - |
| views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP); |
| params.bounds = bounds; |
| - params.native_widget = this; |
| - GetWidget()->Init(params); |
| - if (!IsWindow(GetNativeView())) { |
| +#if defined(USE_AURA) |
| + params.native_widget = new views::DesktopNativeWidgetAura(widget_); |
| +#endif |
| + widget_->Init(params); |
| + HWND window = HWNDFromNativeView(widget_->GetNativeView()); |
| + |
| + if (!IsWindow(window)) { |
|
sky
2013/02/26 17:15:29
I believe Widget::Init CHECKs that an HWND is crea
grt (UTC plus 2)
2013/02/27 16:53:11
Looks like WindowImpl::Init has some CHECKs, so I
|
| NOTREACHED(); |
| return false; |
| } |
| // TODO(jcampan): limit focus traversal to contents. |
| - prop_.reset(new ViewProp(GetNativeView(), kWindowObjectKey, this)); |
| + prop_.reset(new ui::ViewProp(window, kWindowObjectKey, this)); |
| if (existing_contents) { |
| existing_contents->GetController().SetBrowserContext(profile); |
| @@ -242,15 +337,14 @@ bool ExternalTabContainerWin::Init(Profile* profile, |
| // Note that it's important to do this before we call SetParent since |
| // during the SetParent call we will otherwise get a WA_ACTIVATE call |
| // that causes us to steal the current focus. |
| - SetWindowLong( |
| - GetNativeView(), GWL_STYLE, |
| - (GetWindowLong(GetNativeView(), GWL_STYLE) & ~WS_POPUP) | style); |
| + SetWindowLong(window, GWL_STYLE, |
| + (GetWindowLong(window, GWL_STYLE) & ~WS_POPUP) | style); |
| // Now apply the parenting and style |
| if (parent) |
| - SetParent(GetNativeView(), parent); |
| + SetParent(window, parent); |
| - ::ShowWindow(existing_contents->GetNativeView(), SW_SHOWNA); |
| + ShowNativeView(existing_contents->GetNativeView()); |
| LoadAccelerators(); |
| SetupExternalTabView(); |
| @@ -262,6 +356,7 @@ bool ExternalTabContainerWin::Init(Profile* profile, |
| void ExternalTabContainerWin::Uninitialize() { |
| registrar_.RemoveAll(); |
| if (web_contents_.get()) { |
| + tab_contents_container_->SetWebContents(NULL); |
| UnregisterRenderViewHost(web_contents_->GetRenderViewHost()); |
| // Explicitly tell the RPH to shutdown, as doing so is the only thing that |
| @@ -283,8 +378,9 @@ void ExternalTabContainerWin::Uninitialize() { |
| // more fitting. |
| web_contents_->GetRenderProcessHost()->FastShutdownForPageCount(1); |
| - if (GetWidget()->GetRootView()) |
| - GetWidget()->GetRootView()->RemoveAllChildViews(true); |
| + if (widget_->GetRootView()) |
| + widget_->GetRootView()->RemoveAllChildViews(true); |
| + widget_ = NULL; |
| content::NotificationService::current()->Notify( |
| chrome::NOTIFICATION_EXTERNAL_TAB_CLOSED, |
| @@ -307,7 +403,7 @@ void ExternalTabContainerWin::Uninitialize() { |
| bool ExternalTabContainerWin::Reinitialize( |
| AutomationProvider* automation_provider, |
| AutomationResourceMessageFilter* filter, |
| - gfx::NativeWindow parent_window) { |
| + HWND parent_window) { |
| if (!automation_provider || !filter) { |
| NOTREACHED(); |
| return false; |
| @@ -322,7 +418,7 @@ bool ExternalTabContainerWin::Reinitialize( |
| weak_factory_.GetWeakPtr())); |
| if (parent_window) |
| - SetParent(GetNativeView(), parent_window); |
| + SetParent(HWNDFromNativeView(widget_->GetNativeView()), parent_window); |
| return true; |
| } |
| @@ -330,8 +426,12 @@ WebContents* ExternalTabContainerWin::GetWebContents() const { |
| return web_contents_.get(); |
| } |
| -gfx::NativeView ExternalTabContainerWin::GetExternalTabNativeView() const { |
| - return GetNativeView(); |
| +HWND ExternalTabContainerWin::GetExternalTabHWND() const { |
| + return HWNDFromNativeView(widget_->GetNativeView()); |
| +} |
| + |
| +HWND ExternalTabContainerWin::GetContentHWND() const { |
| + return HWNDFromNativeView(web_contents_->GetNativeView()); |
| } |
| void ExternalTabContainerWin::SetTabHandle(int handle) { |
| @@ -388,8 +488,8 @@ void ExternalTabContainerWin::RunUnloadHandlers(IPC::Message* reply_message) { |
| } |
| void ExternalTabContainerWin::ProcessUnhandledAccelerator(const MSG& msg) { |
| - NativeWebKeyboardEvent keyboard_event(msg); |
| - unhandled_keyboard_event_handler_.HandleKeyboardEvent(keyboard_event, |
| + scoped_ptr<NativeWebKeyboardEvent> keyboard_event(CreateKeyboardEvent(msg)); |
| + unhandled_keyboard_event_handler_.HandleKeyboardEvent(*keyboard_event, |
| focus_manager_); |
| } |
| @@ -408,22 +508,6 @@ void ExternalTabContainerWin::FocusThroughTabTraversal( |
| web_contents_->FocusThroughTabTraversal(reverse); |
| } |
| -// static |
| -bool ExternalTabContainerWin::IsExternalTabContainer(HWND window) { |
| - return ViewProp::GetValue(window, kWindowObjectKey) != NULL; |
| -} |
| - |
| -// static |
| -ExternalTabContainer* |
| - ExternalTabContainerWin::GetExternalContainerFromNativeWindow( |
| - gfx::NativeView native_window) { |
| - ExternalTabContainer* tab_container = NULL; |
| - if (native_window) { |
| - tab_container = reinterpret_cast<ExternalTabContainer*>( |
| - ViewProp::GetValue(native_window, kWindowObjectKey)); |
| - } |
| - return tab_container; |
| -} |
| //////////////////////////////////////////////////////////////////////////////// |
| // ExternalTabContainer, content::WebContentsDelegate implementation: |
| @@ -718,7 +802,8 @@ bool ExternalTabContainerWin::HandleContextMenu( |
| ConvertMenuModel(&external_context_menu_->menu_model())); |
| POINT screen_pt = { params.x, params.y }; |
| - MapWindowPoints(GetNativeView(), HWND_DESKTOP, &screen_pt, 1); |
| + MapWindowPoints(HWNDFromNativeView(widget_->GetNativeView()), HWND_DESKTOP, |
| + &screen_pt, 1); |
| MiniContextMenuParams ipc_params; |
| ipc_params.screen_x = screen_pt.x; |
| @@ -749,8 +834,9 @@ bool ExternalTabContainerWin::PreHandleKeyboardEvent( |
| void ExternalTabContainerWin::HandleKeyboardEvent( |
| content::WebContents* source, |
| const NativeWebKeyboardEvent& event) { |
| - ProcessUnhandledKeyStroke(event.os_event.hwnd, event.os_event.message, |
| - event.os_event.wParam, event.os_event.lParam); |
| + const MSG& message = MessageFromKeyboardEvent(event); |
| + ProcessUnhandledKeyStroke(message.hwnd, message.message, |
| + message.wParam, message.lParam); |
| } |
| void ExternalTabContainerWin::BeforeUnloadFired(WebContents* tab, |
| @@ -949,30 +1035,20 @@ void ExternalTabContainerWin::Observe( |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| -// ExternalTabContainer, views::NativeWidgetWin overrides: |
| - |
| -bool ExternalTabContainerWin::PreHandleMSG(UINT message, |
| - WPARAM w_param, |
| - LPARAM l_param, |
| - LRESULT* result) { |
| - if (message == WM_DESTROY) { |
| - prop_.reset(); |
| - Uninitialize(); |
| - } |
| - return false; |
| +// WidgetLifecycleDelegate overrides: |
| + |
| +void ExternalTabContainerWin::OnNativeWidgetCreated() { |
| + // Grab a reference here which will be released in OnNativeWidgetDestroyed. |
| + AddRef(); |
| } |
| -void ExternalTabContainerWin::PostHandleMSG(UINT message, |
| - WPARAM w_param, |
| - LPARAM l_param) { |
| - // Grab a reference here which will be released in OnFinalMessage |
| - if (message == WM_CREATE) |
| - AddRef(); |
| +void ExternalTabContainerWin::OnNativeWidgetDestroying() { |
| + Uninitialize(); |
| + prop_.reset(); |
| } |
| -void ExternalTabContainerWin::OnFinalMessage(HWND window) { |
| - GetWidget()->OnNativeWidgetDestroyed(); |
| - // Release the reference which we grabbed in WM_CREATE. |
| +void ExternalTabContainerWin::OnNativeWidgetDestroyed() { |
| + // Release the reference which we grabbed in OnNativeWidgetCreated. |
| Release(); |
| } |
| @@ -1143,7 +1219,7 @@ void ExternalTabContainerWin::LoadAccelerators() { |
| CopyAcceleratorTable(accelerator_table, accelerators, count); |
| - focus_manager_ = GetWidget()->GetFocusManager(); |
| + focus_manager_ = widget_->GetFocusManager(); |
| DCHECK(focus_manager_); |
| // Let's fill our own accelerator table. |
| @@ -1221,7 +1297,7 @@ void ExternalTabContainerWin::SetupExternalTabView() { |
| layout->AddView(info_bar_container); |
| layout->StartRow(1, 0); |
| layout->AddView(tab_contents_container_); |
| - GetWidget()->SetContentsView(external_tab_view_); |
| + widget_->SetContentsView(external_tab_view_); |
| // Note that SetWebContents must be called after AddChildView is called |
| tab_contents_container_->SetWebContents(web_contents()); |
| } |
| @@ -1235,17 +1311,13 @@ ExternalTabContainer* ExternalTabContainer::Create( |
| // static |
| ExternalTabContainer* ExternalTabContainer::GetContainerForTab( |
| - HWND tab_window) { |
| - HWND parent_window = ::GetParent(tab_window); |
| - if (!::IsWindow(parent_window)) { |
| + content::WebContents* web_contents) { |
| + HWND parent_window = |
| + HWNDFromNativeView(web_contents->GetView()->GetTopLevelNativeWindow()); |
| + if (!::IsWindow(parent_window)) |
| return NULL; |
| - } |
| - if (!ExternalTabContainerWin::IsExternalTabContainer(parent_window)) { |
| - return NULL; |
| - } |
| - ExternalTabContainer* container = reinterpret_cast<ExternalTabContainer*>( |
| - ViewProp::GetValue(parent_window, kWindowObjectKey)); |
| - return container; |
| + return reinterpret_cast<ExternalTabContainerWin*>( |
| + ui::ViewProp::GetValue(parent_window, kWindowObjectKey)); |
| } |
| // static |
| @@ -1282,6 +1354,6 @@ WebContents* TemporaryPopupExternalTabContainerWin::OpenURLFromTab( |
| WebContents* new_contents = |
| ExternalTabContainerWin::OpenURLFromTab(source, forward_params); |
| // support only one navigation for a dummy tab before it is killed. |
| - ::DestroyWindow(GetNativeView()); |
| + widget_->CloseNow(); |
| return new_contents; |
| } |