diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/SConscript | 1 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 4 | ||||
-rw-r--r-- | chrome/browser/render_view_host.cc | 21 | ||||
-rw-r--r-- | chrome/browser/render_view_host.h | 2 | ||||
-rw-r--r-- | chrome/browser/render_view_host_delegate.h | 47 | ||||
-rw-r--r-- | chrome/browser/render_widget_helper.cc | 14 | ||||
-rw-r--r-- | chrome/browser/render_widget_helper.h | 6 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view.h | 12 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.cc | 23 | ||||
-rw-r--r-- | chrome/browser/render_widget_host_view_win.h | 4 | ||||
-rw-r--r-- | chrome/browser/resource_message_filter.cc | 16 | ||||
-rw-r--r-- | chrome/browser/resource_message_filter.h | 4 | ||||
-rw-r--r-- | chrome/browser/web_contents.cc | 113 | ||||
-rw-r--r-- | chrome/browser/web_contents.h | 16 | ||||
-rw-r--r-- | chrome/browser/web_contents_unittest.cc | 50 | ||||
-rw-r--r-- | chrome/browser/web_contents_view.cc | 47 | ||||
-rw-r--r-- | chrome/browser/web_contents_view.h | 59 | ||||
-rw-r--r-- | chrome/browser/web_contents_view_win.cc | 104 | ||||
-rw-r--r-- | chrome/browser/web_contents_view_win.h | 15 |
19 files changed, 358 insertions, 200 deletions
diff --git a/chrome/browser/SConscript b/chrome/browser/SConscript index a93544a..780a8a1 100644 --- a/chrome/browser/SConscript +++ b/chrome/browser/SConscript @@ -289,6 +289,7 @@ if env['PLATFORM'] == 'win32': 'web_app_icon_manager.cc', 'web_app_launcher.cc', 'web_contents.cc', + 'web_contents_view.cc', 'web_drag_source.cc', 'web_drop_target.cc', 'webdata/web_data_service.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 743e775..2d3f6e8 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -894,6 +894,10 @@ > </File> <File + RelativePath=".\web_contents_view.cc" + > + </File> + <File RelativePath=".\web_contents_view.h" > </File> diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc index 990e4c0..54376cf 100644 --- a/chrome/browser/render_view_host.cc +++ b/chrome/browser/render_view_host.cc @@ -599,7 +599,7 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) { bool msg_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(RenderViewHost, msg, msg_is_ok) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateViewWithRoute, OnMsgCreateView) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindowWithRoute, OnMsgCreateWindow) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidgetWithRoute, OnMsgCreateWidget) IPC_MESSAGE_HANDLER(ViewHostMsg_ShowView, OnMsgShowView) IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnMsgShowWidget) @@ -701,24 +701,33 @@ void RenderViewHost::Shutdown() { RenderWidgetHost::Shutdown(); } -void RenderViewHost::OnMsgCreateView(int route_id, HANDLE modal_dialog_event) { - delegate_->CreateView(route_id, modal_dialog_event); +void RenderViewHost::OnMsgCreateWindow(int route_id, + HANDLE modal_dialog_event) { + RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); + if (view) + view->CreateNewWindow(route_id, modal_dialog_event); } void RenderViewHost::OnMsgCreateWidget(int route_id) { - delegate_->CreateWidget(route_id); + RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); + if (view) + view->CreateNewWidget(route_id); } void RenderViewHost::OnMsgShowView(int route_id, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture) { - delegate_->ShowView(route_id, disposition, initial_pos, user_gesture); + RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); + if (view) + view->ShowCreatedWindow(route_id, disposition, initial_pos, user_gesture); } void RenderViewHost::OnMsgShowWidget(int route_id, const gfx::Rect& initial_pos) { - delegate_->ShowWidget(route_id, initial_pos); + RenderViewHostDelegate::View* view = delegate_->GetViewDelegate(); + if (view) + view->ShowCreatedWidget(route_id, initial_pos); } void RenderViewHost::OnMsgRunModal(IPC::Message* reply_msg) { diff --git a/chrome/browser/render_view_host.h b/chrome/browser/render_view_host.h index 98b045a..a20bac7a5 100644 --- a/chrome/browser/render_view_host.h +++ b/chrome/browser/render_view_host.h @@ -387,7 +387,7 @@ class RenderViewHost : public RenderWidgetHost { virtual void UnhandledInputEvent(const WebInputEvent& event); // IPC message handlers: - void OnMsgCreateView(int route_id, HANDLE modal_dialog_event); + void OnMsgCreateWindow(int route_id, HANDLE modal_dialog_event); void OnMsgCreateWidget(int route_id); void OnMsgShowView(int route_id, WindowOpenDisposition disposition, diff --git a/chrome/browser/render_view_host_delegate.h b/chrome/browser/render_view_host_delegate.h index eb1cef6..4593f10 100644 --- a/chrome/browser/render_view_host_delegate.h +++ b/chrome/browser/render_view_host_delegate.h @@ -47,6 +47,37 @@ enum LoadState; // class RenderViewHostDelegate { public: + class View { + public: + // The page is trying to open a new page (e.g. a popup window). The + // window should be created associated with the given route, but it should + // not be shown yet. That should happen in response to ShowCreatedWindow. + // + // Note: this is not called "CreateWindow" because that will clash with + // the Windows function which is actually a #define. + virtual void CreateNewWindow(int route_id, HANDLE modal_dialog_event) = 0; + + // The page is trying to open a new widget (e.g. a select popup). The + // widget should be created associated with the given route, but it should + // not be shown yet. That should happen in response to ShowCreatedWidget. + virtual void CreateNewWidget(int route_id) = 0; + + // Show a previously created page with the specified disposition and bounds. + // The window is identified by the route_id passed to CreateNewWindow. + // + // Note: this is not called "ShowWindow" because that will clash with + // the Windows function which is actually a #define. + virtual void ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) = 0; + + // Show the newly created widget with the specified bounds. + // The widget is identified by the route_id passed to CreateNewWidget. + virtual void ShowCreatedWidget(int route_id, + const gfx::Rect& initial_pos) = 0; + }; + class FindInPage { public: // A find operation in the current page completed. @@ -81,27 +112,13 @@ class RenderViewHostDelegate { }; // Returns the current delegate associated with a feature. May be NULL. + virtual View* GetViewDelegate() const { return NULL; } virtual FindInPage* GetFindInPageDelegate() const { return NULL; } virtual Save* GetSaveDelegate() const { return NULL; } // Retrieves the profile to be used. virtual Profile* GetProfile() const = 0; - // The page is trying to open a new page (e.g. a popup window). - virtual void CreateView(int route_id, HANDLE modal_dialog_event) { } - - // The page is trying to open a new widget (e.g. a select popup). - virtual void CreateWidget(int route_id) { } - - // Show the newly created page with the specified disposition and bounds. - virtual void ShowView(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { } - - // Show the newly created widget with the specified bounds. - virtual void ShowWidget(int route_id, const gfx::Rect& initial_pos) { } - // The RenderView is being constructed (message sent to the renderer process // to construct a RenderView). Now is a good time to send other setup events // to the RenderView. This precedes any other commands to the RenderView. diff --git a/chrome/browser/render_widget_helper.cc b/chrome/browser/render_widget_helper.cc index d2554e6..3f91834 100644 --- a/chrome/browser/render_widget_helper.cc +++ b/chrome/browser/render_widget_helper.cc @@ -187,11 +187,11 @@ void RenderWidgetHelper::OnCrossSiteClosePageACK( dispatcher->OnClosePageACK(new_render_process_host_id, new_request_id); } -void RenderWidgetHelper::CreateView(int opener_id, - bool user_gesture, - int* route_id, - HANDLE* modal_dialog_event, - HANDLE render_process) { +void RenderWidgetHelper::CreateNewWindow(int opener_id, + bool user_gesture, + int* route_id, + HANDLE* modal_dialog_event, + HANDLE render_process) { if (!user_gesture && block_popups_) { *route_id = MSG_ROUTING_NONE; *modal_dialog_event = NULL; @@ -210,12 +210,12 @@ void RenderWidgetHelper::CreateView(int opener_id, DCHECK(result) << "Couldn't duplicate modal dialog event for the renderer."; // The easiest way to reach RenderViewHost is just to send a routed message. - ViewHostMsg_CreateViewWithRoute msg(opener_id, *route_id, event); + ViewHostMsg_CreateWindowWithRoute msg(opener_id, *route_id, event); ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( this, &RenderWidgetHelper::OnSimulateReceivedMessage, msg)); } -void RenderWidgetHelper::CreateWidget(int opener_id, int* route_id) { +void RenderWidgetHelper::CreateNewWidget(int opener_id, int* route_id) { *route_id = GetNextRoutingID(); ViewHostMsg_CreateWidgetWithRoute msg(opener_id, *route_id); ui_loop_->PostTask(FROM_HERE, NewRunnableMethod( diff --git a/chrome/browser/render_widget_helper.h b/chrome/browser/render_widget_helper.h index 6098289..96de62a 100644 --- a/chrome/browser/render_widget_helper.h +++ b/chrome/browser/render_widget_helper.h @@ -108,9 +108,9 @@ class RenderWidgetHelper : MessageLoop* ui_loop() { return ui_loop_; } - void CreateView(int opener_id, bool user_gesture, int* route_id, - HANDLE* modal_dialog_event, HANDLE render_process); - void CreateWidget(int opener_id, int* route_id); + void CreateNewWindow(int opener_id, bool user_gesture, int* route_id, + HANDLE* modal_dialog_event, HANDLE render_process); + void CreateNewWidget(int opener_id, int* route_id); private: // A class used to proxy a paint message. PaintMsgProxy objects are created diff --git a/chrome/browser/render_widget_host_view.h b/chrome/browser/render_widget_host_view.h index a94add7..be9c128 100644 --- a/chrome/browser/render_widget_host_view.h +++ b/chrome/browser/render_widget_host_view.h @@ -18,6 +18,8 @@ namespace IPC { class Message; } +class RenderProcessHost; +class RenderWidgetHost; class WebCursor; /////////////////////////////////////////////////////////////////////////////// @@ -35,6 +37,16 @@ class WebCursor; /////////////////////////////////////////////////////////////////////////////// class RenderWidgetHostView { public: + // Platform-specific creator. Use this to construct new RenderWidgetHostViews + // rather than using RenderWidgetHostViewWin & friends. + // + // The RenderWidgetHost must already be created (because we can't know if it's + // going to be a regular RenderWidgetHost or a RenderViewHost (a subclass). + static RenderWidgetHostView* CreateViewForWidget(RenderWidgetHost* widget); + + // Returns the associated RenderWidgetHost. + virtual RenderWidgetHost* GetRenderWidgetHost() const = 0; + // Notifies the View that it has become visible. virtual void DidBecomeSelected() = 0; diff --git a/chrome/browser/render_widget_host_view_win.cc b/chrome/browser/render_widget_host_view_win.cc index db70018..32d6d55 100644 --- a/chrome/browser/render_widget_host_view_win.cc +++ b/chrome/browser/render_widget_host_view_win.cc @@ -50,13 +50,21 @@ BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { } // namespace +// RenderWidgetHostView -------------------------------------------------------- + +// static +RenderWidgetHostView* RenderWidgetHostView::CreateViewForWidget( + RenderWidgetHost* widget) { + return new RenderWidgetHostViewWin(widget); +} + /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewWin, public: RenderWidgetHostViewWin::RenderWidgetHostViewWin( - RenderWidgetHost* render_widget_host) + RenderWidgetHost* widget) : RenderWidgetHostView(), - render_widget_host_(render_widget_host), + render_widget_host_(widget), real_cursor_(LoadCursor(NULL, IDC_ARROW)), real_cursor_type_(WebCursor::ARROW), track_mouse_leave_(false), @@ -68,6 +76,13 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin( shutdown_factory_(this), parent_hwnd_(NULL), is_loading_(false) { + render_widget_host_->set_view(this); + + // We set the parent HWND explicitly as pop-up HWNDs are parented and owned by + // the first non-child HWND of the HWND that was specified to the CreateWindow + // call. + set_parent_hwnd(GetPluginHWND()); + set_close_on_deactivate(true); } RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { @@ -79,6 +94,10 @@ RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewWin, RenderWidgetHostView implementation: +RenderWidgetHost* RenderWidgetHostViewWin::GetRenderWidgetHost() const { + return render_widget_host_; +} + void RenderWidgetHostViewWin::DidBecomeSelected() { if (!is_hidden_) return; diff --git a/chrome/browser/render_widget_host_view_win.h b/chrome/browser/render_widget_host_view_win.h index d49b9de..9db04ce 100644 --- a/chrome/browser/render_widget_host_view_win.h +++ b/chrome/browser/render_widget_host_view_win.h @@ -57,7 +57,8 @@ class RenderWidgetHostViewWin : RenderWidgetHostHWNDTraits>, public RenderWidgetHostView { public: - explicit RenderWidgetHostViewWin(RenderWidgetHost* render_widget_host); + // The view will associate itself with the given widget. + explicit RenderWidgetHostViewWin(RenderWidgetHost* widget); virtual ~RenderWidgetHostViewWin(); void set_close_on_deactivate(bool close_on_deactivate) { @@ -113,6 +114,7 @@ class RenderWidgetHostViewWin : END_MSG_MAP() // Implementation of RenderWidgetHostView: + virtual RenderWidgetHost* GetRenderWidgetHost() const; virtual void DidBecomeSelected(); virtual void WasHidden(); virtual void SetSize(const gfx::Size& size); diff --git a/chrome/browser/resource_message_filter.cc b/chrome/browser/resource_message_filter.cc index 5afe628..403fa63 100644 --- a/chrome/browser/resource_message_filter.cc +++ b/chrome/browser/resource_message_filter.cc @@ -143,7 +143,7 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; bool msg_is_ok = true; IPC_BEGIN_MESSAGE_MAP_EX(ResourceMessageFilter, message, msg_is_ok) - IPC_MESSAGE_HANDLER(ViewHostMsg_CreateView, OnMsgCreateView) + IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) // TODO(brettw): we should get the view ID for this so the resource // dispatcher can prioritize things based on the visible view. @@ -286,16 +286,16 @@ bool ResourceMessageFilter::Send(IPC::Message* message) { return channel_->Send(message); } -void ResourceMessageFilter::OnMsgCreateView(int opener_id, - bool user_gesture, - int* route_id, - HANDLE* modal_dialog_event) { - render_widget_helper_->CreateView(opener_id, user_gesture, route_id, - modal_dialog_event, render_handle_); +void ResourceMessageFilter::OnMsgCreateWindow(int opener_id, + bool user_gesture, + int* route_id, + HANDLE* modal_dialog_event) { + render_widget_helper_->CreateNewWindow(opener_id, user_gesture, route_id, + modal_dialog_event, render_handle_); } void ResourceMessageFilter::OnMsgCreateWidget(int opener_id, int* route_id) { - render_widget_helper_->CreateWidget(opener_id, route_id); + render_widget_helper_->CreateNewWidget(opener_id, route_id); } void ResourceMessageFilter::OnRequestResource( diff --git a/chrome/browser/resource_message_filter.h b/chrome/browser/resource_message_filter.h index aee07c1..5cd9d11 100644 --- a/chrome/browser/resource_message_filter.h +++ b/chrome/browser/resource_message_filter.h @@ -69,8 +69,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, const NotificationDetails& details); private: - void OnMsgCreateView(int opener_id, bool user_gesture, int* route_id, - HANDLE* modal_dialog_event); + void OnMsgCreateWindow(int opener_id, bool user_gesture, int* route_id, + HANDLE* modal_dialog_event); void OnMsgCreateWidget(int opener_id, int* route_id); void OnRequestResource(const IPC::Message& msg, int request_id, const ViewHostMsg_Resource_Request& request); diff --git a/chrome/browser/web_contents.cc b/chrome/browser/web_contents.cc index b635785..cdee437 100644 --- a/chrome/browser/web_contents.cc +++ b/chrome/browser/web_contents.cc @@ -193,9 +193,10 @@ WebContents::WebContents(Profile* profile, // Register for notifications about all interested prefs change. PrefService* prefs = profile->GetPrefs(); - if (prefs) + if (prefs) { for (int i = 0; i < kPrefsToObserveLength; ++i) prefs->AddPrefObserver(kPrefsToObserve[i], this); + } // Register for notifications about URL starredness changing on any profile. NotificationService::current()-> @@ -699,6 +700,10 @@ void WebContents::SetIsLoading(bool is_loading, render_manager_.SetIsLoading(is_loading); } +RenderViewHostDelegate::View* WebContents::GetViewDelegate() const { + return view_.get(); +} + RenderViewHostDelegate::FindInPage* WebContents::GetFindInPageDelegate() const { // The find in page controller implements this interface for us. Our return // value can be NULL, so it's fine if the find in controller doesn't exist. @@ -713,103 +718,6 @@ Profile* WebContents::GetProfile() const { return profile(); } -void WebContents::CreateView(int route_id, HANDLE modal_dialog_event) { - // TODO(brettw) move this to the view. - WebContents* new_view = new WebContents(profile(), - GetSiteInstance(), - render_view_factory_, - route_id, - modal_dialog_event); - new_view->SetupController(profile()); - // TODO(beng) - // The intention here is to create background tabs, which should ideally - // be parented to NULL. However doing that causes the corresponding view - // container windows to show up as overlapped windows, which causes - // other issues. We should fix this. - HWND new_view_parent_window = ::GetAncestor(GetContainerHWND(), GA_ROOT); - new_view->CreateView(new_view_parent_window, gfx::Rect()); - // TODO(brettw) it seems bogus that we have to call this function on the - // newly created object and give it one of its own member variables. - new_view->view_->CreatePageView(new_view->render_view_host()); - - // Don't show the view until we get enough context in ShowView. - pending_views_[route_id] = new_view; -} - -void WebContents::CreateWidget(int route_id) { - RenderWidgetHost* widget_host = new RenderWidgetHost(process(), route_id); - // TODO(brettw) createe the view in some cross-platform way (probably move - // to the WebContentsView). CreatePageView seems to do this already? This - // is confusing. - RenderWidgetHostViewWin* widget_view = - new RenderWidgetHostViewWin(widget_host); - widget_host->set_view(widget_view); - // We set the parent HWDN explicitly as pop-up HWNDs are parented and owned by - // the first non-child HWND of the HWND that was specified to the CreateWindow - // call. - widget_view->set_parent_hwnd(render_widget_host_view()->GetPluginHWND()); - widget_view->set_close_on_deactivate(true); - - // Don't show the widget until we get its position in ShowWidget. - pending_widgets_[route_id] = widget_host; -} - -void WebContents::ShowView(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - PendingViews::iterator iter = pending_views_.find(route_id); - if (iter == pending_views_.end()) { - DCHECK(false); - return; - } - - WebContents* new_web_contents = iter->second; - pending_views_.erase(route_id); - - if (!new_web_contents->render_widget_host_view() || - !new_web_contents->process()->channel()) { - // The view has gone away or the renderer crashed. Nothing to do. - return; - } - - // TODO(brettw) this seems bogus to reach into here and initialize the host. - new_web_contents->render_view_host()->Init(); - AddNewContents(new_web_contents, disposition, initial_pos, user_gesture); -} - -void WebContents::ShowWidget(int route_id, const gfx::Rect& initial_pos) { - PendingWidgets::iterator iter = pending_widgets_.find(route_id); - if (iter == pending_widgets_.end()) { - DCHECK(false); - return; - } - - RenderWidgetHost* widget_host = iter->second; - pending_widgets_.erase(route_id); - - // TODO(beng): (Cleanup) move all this windows-specific creation and showing - // code into RenderWidgetHostViewWin behind some API that a - // ChromeView can also reasonably implement. - RenderWidgetHostViewWin* widget_view = - static_cast<RenderWidgetHostViewWin*>(widget_host->view()); - - if (!widget_view || !widget_host->process()->channel()) { - // The view has gone away or the renderer crashed. Nothing to do. - return; - } - - // This logic should be implemented by RenderWidgetHostViewWin (as mentioned - // above) in the ::Init function, which should take a parent and some initial - // bounds. - widget_view->Create(view_->GetContainerHWND(), NULL, NULL, - WS_POPUP, WS_EX_TOOLWINDOW); - widget_view->MoveWindow(initial_pos.x(), initial_pos.y(), initial_pos.width(), - initial_pos.height(), TRUE); - widget_view->ShowWindow(SW_SHOW); - widget_host->Init(); -} - void WebContents::RendererReady(RenderViewHost* rvh) { if (render_manager_.showing_interstitial_page() && rvh == render_view_host()) { @@ -1604,13 +1512,14 @@ void WebContents::UpdateRenderViewSizeForRenderManager() { bool WebContents::CreateRenderViewForRenderManager( RenderViewHost* render_view_host) { - // TODO(brettw) move this to the view. Probably the RenderWidgetHostViewWins - // should be created by a factory somewhere that just returns a - // RenderWidgetHostView*. - RenderWidgetHostViewWin* rvh_view = view_->CreatePageView(render_view_host); + RenderWidgetHostView* rvh_view = view_->CreateViewForWidget(render_view_host); bool ok = render_view_host->CreateRenderView(); if (ok) { + // TODO(brettw) hack alert. Do this in some cross platform way, or move + // to the view? + RenderWidgetHostViewWin* rvh_view_win = + static_cast<RenderWidgetHostViewWin*>(rvh_view); rvh_view->SetSize(view_->GetContainerSize()); UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), render_view_host); diff --git a/chrome/browser/web_contents.h b/chrome/browser/web_contents.h index 1724ea1..5dcb63d 100644 --- a/chrome/browser/web_contents.h +++ b/chrome/browser/web_contents.h @@ -221,16 +221,10 @@ class WebContents : public TabContents, // RenderViewHostDelegate ---------------------------------------------------- + virtual RenderViewHostDelegate::View* GetViewDelegate() const; virtual RenderViewHostDelegate::FindInPage* GetFindInPageDelegate() const; virtual RenderViewHostDelegate::Save* GetSaveDelegate() const; virtual Profile* GetProfile() const; - virtual void CreateView(int route_id, HANDLE modal_dialog_event); - virtual void CreateWidget(int route_id); - virtual void ShowView(int route_id, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ShowWidget(int route_id, const gfx::Rect& initial_pos); virtual void RendererReady(RenderViewHost* render_view_host); virtual void RendererGone(RenderViewHost* render_view_host); virtual void DidNavigate(RenderViewHost* render_view_host, @@ -558,14 +552,6 @@ class WebContents : public TabContents, net::LoadState load_state_; std::wstring load_state_host_; - // These maps hold on to the pages/widgets that we created on behalf of the - // renderer that haven't shown yet. - typedef base::hash_map<int, WebContents*> PendingViews; - PendingViews pending_views_; - - typedef base::hash_map<int, RenderWidgetHost*> PendingWidgets; - PendingWidgets pending_widgets_; - // Non-null if we're displaying content for a web app. scoped_refptr<WebApp> web_app_; diff --git a/chrome/browser/web_contents_unittest.cc b/chrome/browser/web_contents_unittest.cc index 932af42..a4b57f1 100644 --- a/chrome/browser/web_contents_unittest.cc +++ b/chrome/browser/web_contents_unittest.cc @@ -21,32 +21,34 @@ class TestRenderWidgetHostView : public RenderWidgetHostView { public: TestRenderWidgetHostView() {} - void DidBecomeSelected() {} - void WasHidden() {} - void SetSize(const gfx::Size& size) {} - HWND GetPluginHWND() { return NULL; } - HANDLE ModalDialogEvent() { return NULL; } - void ForwardMouseEventToRenderer(UINT message, - WPARAM wparam, - LPARAM lparam) {} - void Focus() {} - void Blur() {} - bool HasFocus() { return true; } - void AdvanceFocus(bool reverse) {} - void Show() {} - void Hide() {} - gfx::Rect GetViewBounds() const { return gfx::Rect(); } - void UpdateCursor(const WebCursor& cursor) {} - void UpdateCursorIfOverSelf() {} + + virtual RenderWidgetHost* GetRenderWidgetHost() const { return NULL; } + virtual void DidBecomeSelected() {} + virtual void WasHidden() {} + virtual void SetSize(const gfx::Size& size) {} + virtual HWND GetPluginHWND() { return NULL; } + virtual HANDLE ModalDialogEvent() { return NULL; } + virtual void ForwardMouseEventToRenderer(UINT message, + WPARAM wparam, + LPARAM lparam) {} + virtual void Focus() {} + virtual void Blur() {} + virtual bool HasFocus() { return true; } + virtual void AdvanceFocus(bool reverse) {} + virtual void Show() {} + virtual void Hide() {} + virtual gfx::Rect GetViewBounds() const { return gfx::Rect(); } + virtual void UpdateCursor(const WebCursor& cursor) {} + virtual void UpdateCursorIfOverSelf() {} // Indicates if the page has finished loading. virtual void SetIsLoading(bool is_loading) {} - void IMEUpdateStatus(ViewHostMsg_ImeControl control, int x, int y) {} - void DidPaintRect(const gfx::Rect& rect) {} - void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} - void RendererGone() {} - void Destroy() {} - void PrepareToDestroy() {} - void SetTooltipText(const std::wstring& tooltip_text) {} + virtual void IMEUpdateStatus(ViewHostMsg_ImeControl control, int x, int y) {} + virtual void DidPaintRect(const gfx::Rect& rect) {} + virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {} + virtual void RendererGone() {} + virtual void Destroy() {} + virtual void PrepareToDestroy() {} + virtual void SetTooltipText(const std::wstring& tooltip_text) {} }; // Subclass RenderViewHost so that it does not create a process. diff --git a/chrome/browser/web_contents_view.cc b/chrome/browser/web_contents_view.cc new file mode 100644 index 0000000..28dd88b --- /dev/null +++ b/chrome/browser/web_contents_view.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2006-2008 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 "chrome/browser/web_contents_view.h" + +void WebContentsView::CreateNewWindow(int route_id, HANDLE modal_dialog_event) { + // Save the created window associated with the route so we can show it later. + pending_contents_[route_id] = CreateNewWindowInternal(route_id, + modal_dialog_event); +} + +void WebContentsView::CreateNewWidget(int route_id) { + // Save the created widget associated with the route so we can show it later. + pending_widget_views_[route_id] = CreateNewWidgetInternal(route_id); +} + +void WebContentsView::ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + PendingContents::iterator iter = pending_contents_.find(route_id); + if (iter == pending_contents_.end()) { + DCHECK(false); + return; + } + + WebContents* new_web_contents = iter->second; + pending_contents_.erase(route_id); + + ShowCreatedWindowInternal(new_web_contents, disposition, initial_pos, + user_gesture); +} + +void WebContentsView::ShowCreatedWidget(int route_id, + const gfx::Rect& initial_pos) { + PendingWidgetViews::iterator iter = pending_widget_views_.find(route_id); + if (iter == pending_widget_views_.end()) { + DCHECK(false); + return; + } + + RenderWidgetHostView* widget_host_view = iter->second; + pending_widget_views_.erase(route_id); + + ShowCreatedWidgetInternal(widget_host_view, initial_pos); +} diff --git a/chrome/browser/web_contents_view.h b/chrome/browser/web_contents_view.h index e21726f..b64760c 100644 --- a/chrome/browser/web_contents_view.h +++ b/chrome/browser/web_contents_view.h @@ -7,16 +7,19 @@ #include <windows.h> +#include <map> #include <string> #include "base/basictypes.h" #include "base/gfx/rect.h" #include "base/gfx/size.h" +#include "chrome/browser/render_view_host_delegate.h" class InfoBarView; class RenderViewHost; class RenderWidgetHost; -class RenderWidgetHostViewWin; +class RenderWidgetHostView; +class RenderWidgetHostViewWin; // TODO(brettw) this should not be necessary. struct ViewHostMsg_ContextMenu_Params; class WebContents; struct WebDropData; @@ -24,8 +27,12 @@ class WebKeyboardEvent; // The WebContentsView is an interface that is implemented by the platform- // dependent web contents views. The WebContents uses this interface to talk to -// them. -class WebContentsView { +// them. View-related messages will also get forwarded directly to this class +// from RenderViewHost via RenderViewHostDelegate::View. +// +// It contains a small amount of logic with respect to creating new sub-view +// that should be the same for all platforms. +class WebContentsView : public RenderViewHostDelegate::View { public: virtual ~WebContentsView() {} @@ -34,9 +41,10 @@ class WebContentsView { // Sets up the View that holds the rendered web page, receives messages for // it and contains page plugins. - // TODO(brettw) this should be a RenderWidgetHostView instead. - virtual RenderWidgetHostViewWin* CreatePageView( - RenderViewHost* render_view_host) = 0; + // TODO(brettw) make this so we don't need to return the Win version (see the + // caller in WebContents). + virtual RenderWidgetHostViewWin* CreateViewForWidget( + RenderWidgetHost* render_widget_host) = 0; // Returns the HWND that contains the contents of the tab. // TODO(brettw) this should not be necessary in this cross-platform interface. @@ -103,7 +111,46 @@ class WebContentsView { protected: WebContentsView() {} // Abstract interface. + // Internal interface for the RenderViewHostDelegate::View interface. + // Subclasses should implement this rather thank ...::View directly, since the + // routing stuff will already be computed. + // + // The only difference is that the Create functions return the newly + // created objects so that they can be associated with the given routes. When + // they are shown later, we'll look them up again and pass the objects to + // the Show functions rather than the route ID. + virtual WebContents* CreateNewWindowInternal(int route_id, + HANDLE modal_dialog_event) = 0; + virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id) = 0; + virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) = 0; + virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos) = 0; + private: + // We implement RenderViewHostDelegate::View directly and do some book-keeping + // associated with the request. The request is then forwarded to *Internal + // which does platform-specific work. + virtual void CreateNewWindow(int route_id, HANDLE modal_dialog_event); + virtual void CreateNewWidget(int route_id); + virtual void ShowCreatedWindow(int route_id, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture); + virtual void ShowCreatedWidget(int route_id, const gfx::Rect& initial_pos); + + // Tracks created WebContents objects that have not been shown yet. They are + // identified by the route ID passed to CreateNewWindow. + typedef std::map<int, WebContents*> PendingContents; + PendingContents pending_contents_; + + // These maps hold on to the widgets that we created on behalf of the + // renderer that haven't shown yet. + typedef std::map<int, RenderWidgetHostView*> PendingWidgetViews; + PendingWidgetViews pending_widget_views_; + DISALLOW_COPY_AND_ASSIGN(WebContentsView); }; diff --git a/chrome/browser/web_contents_view_win.cc b/chrome/browser/web_contents_view_win.cc index 96aeabd..5a377de 100644 --- a/chrome/browser/web_contents_view_win.cc +++ b/chrome/browser/web_contents_view_win.cc @@ -54,12 +54,11 @@ void WebContentsViewWin::CreateView(HWND parent_hwnd, drop_target_ = new WebDropTarget(GetHWND(), web_contents_); } -RenderWidgetHostViewWin* WebContentsViewWin::CreatePageView( - RenderViewHost* render_view_host) { - // Create the View as well. Its lifetime matches the child process'. - DCHECK(!render_view_host->view()); - RenderWidgetHostViewWin* view = new RenderWidgetHostViewWin(render_view_host); - render_view_host->set_view(view); +RenderWidgetHostViewWin* WebContentsViewWin::CreateViewForWidget( + RenderWidgetHost* render_widget_host) { + DCHECK(!render_widget_host->view()); + RenderWidgetHostViewWin* view = + new RenderWidgetHostViewWin(render_widget_host); view->Create(GetHWND()); view->ShowWindow(SW_SHOW); return view; @@ -217,6 +216,99 @@ void WebContentsViewWin::HandleKeyboardEvent(const WebKeyboardEvent& event) { event.actual_message.lParam); } +WebContents* WebContentsViewWin::CreateNewWindowInternal( + int route_id, + HANDLE modal_dialog_event) { + // Create the new web contents. This will automatically create the new + // WebContentsView. In the future, we may want to create the view separately. + WebContents* new_contents = + new WebContents(web_contents_->profile(), + web_contents_->GetSiteInstance(), + web_contents_->render_view_factory_, + route_id, + modal_dialog_event); + new_contents->SetupController(web_contents_->profile()); + WebContentsView* new_view = new_contents->view(); + + // TODO(beng) + // The intention here is to create background tabs, which should ideally + // be parented to NULL. However doing that causes the corresponding view + // container windows to show up as overlapped windows, which causes + // other issues. We should fix this. + HWND new_view_parent_window = ::GetAncestor(GetContainerHWND(), GA_ROOT); + new_view->CreateView(new_view_parent_window, gfx::Rect()); + + // TODO(brettw) it seems bogus that we have to call this function on the + // newly created object and give it one of its own member variables. + new_view->CreateViewForWidget(new_contents->render_view_host()); + return new_contents; +} + +RenderWidgetHostView* WebContentsViewWin::CreateNewWidgetInternal( + int route_id) { + // Create the widget and its associated view. + // TODO(brettw) can widget creation be cross-platform? + RenderWidgetHost* widget_host = + new RenderWidgetHost(web_contents_->process(), route_id); + RenderWidgetHostViewWin* widget_view = + new RenderWidgetHostViewWin(widget_host); + + // We set the parent HWDN explicitly as pop-up HWNDs are parented and owned by + // the first non-child HWND of the HWND that was specified to the CreateWindow + // call. + // TODO(brettw) this should not need to get the current RVHView from the + // WebContents. We should have it somewhere ourselves. + widget_view->set_parent_hwnd( + web_contents_->render_widget_host_view()->GetPluginHWND()); + widget_view->set_close_on_deactivate(true); + + return widget_view; +} + +void WebContentsViewWin::ShowCreatedWindowInternal( + WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture) { + if (!new_web_contents->render_widget_host_view() || + !new_web_contents->process()->channel()) { + // The view has gone away or the renderer crashed. Nothing to do. + return; + } + + // TODO(brettw) this seems bogus to reach into here and initialize the host. + new_web_contents->render_view_host()->Init(); + web_contents_->AddNewContents(new_web_contents, disposition, initial_pos, + user_gesture); +} + +void WebContentsViewWin::ShowCreatedWidgetInternal( + RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos) { + // TODO(beng): (Cleanup) move all this windows-specific creation and showing + // code into RenderWidgetHostView behind some API that a + // ChromeView can also reasonably implement. + RenderWidgetHostViewWin* widget_host_view_win = + static_cast<RenderWidgetHostViewWin*>(widget_host_view); + + RenderWidgetHost* widget_host = widget_host_view->GetRenderWidgetHost(); + if (!widget_host->process()->channel()) { + // The view has gone away or the renderer crashed. Nothing to do. + return; + } + + // This logic should be implemented by RenderWidgetHostHWND (as mentioned + // above) in the ::Init function, which should take a parent and some initial + // bounds. + widget_host_view_win->Create(GetContainerHWND(), NULL, NULL, + WS_POPUP, WS_EX_TOOLWINDOW); + widget_host_view_win->MoveWindow(initial_pos.x(), initial_pos.y(), + initial_pos.width(), initial_pos.height(), + TRUE); + widget_host_view_win->ShowWindow(SW_SHOW); + widget_host->Init(); +} + void WebContentsViewWin::OnHScroll(int scroll_type, short position, HWND scrollbar) { ScrollCommon(WM_HSCROLL, scroll_type, position, scrollbar); diff --git a/chrome/browser/web_contents_view_win.h b/chrome/browser/web_contents_view_win.h index 3a905be..157b070 100644 --- a/chrome/browser/web_contents_view_win.h +++ b/chrome/browser/web_contents_view_win.h @@ -30,8 +30,8 @@ class WebContentsViewWin : public WebContentsView, // CreatePageView. Do we really need both? virtual void CreateView(HWND parent_hwnd, const gfx::Rect& initial_bounds); - virtual RenderWidgetHostViewWin* CreatePageView( - RenderViewHost* render_view_host); + virtual RenderWidgetHostViewWin* CreateViewForWidget( + RenderWidgetHost* render_widget_host); virtual HWND GetContainerHWND() const; virtual HWND GetContentHWND() const; virtual void GetContainerBounds(gfx::Rect* out) const; @@ -46,6 +46,17 @@ class WebContentsViewWin : public WebContentsView, const ViewHostMsg_ContextMenu_Params& params); virtual void HandleKeyboardEvent(const WebKeyboardEvent& event); + // Backend implementation of RenderViewHostDelegate::View. + virtual WebContents* CreateNewWindowInternal( + int route_id, HANDLE modal_dialog_event); + virtual RenderWidgetHostView* CreateNewWidgetInternal(int route_id); + virtual void ShowCreatedWindowInternal(WebContents* new_web_contents, + WindowOpenDisposition disposition, + const gfx::Rect& initial_pos, + bool user_gesture); + virtual void ShowCreatedWidgetInternal(RenderWidgetHostView* widget_host_view, + const gfx::Rect& initial_pos); + private: // Windows events ------------------------------------------------------------ |