summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 15:29:03 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-17 15:29:03 +0000
commit15787f8f3946a513d39a1f0d9a12925f447fa18d (patch)
tree9f68bab4d2682376d7d11ec42024f67823470427 /chrome
parent0d05594d912d67dcbcd5b899a1036819603922b1 (diff)
downloadchromium_src-15787f8f3946a513d39a1f0d9a12925f447fa18d.zip
chromium_src-15787f8f3946a513d39a1f0d9a12925f447fa18d.tar.gz
chromium_src-15787f8f3946a513d39a1f0d9a12925f447fa18d.tar.bz2
Separate out most view creation from WebContents. This adds a new sub-delegate to RenderViewHostDelegate which is implemented by WebContentsView. I did a lot of plumbing and moving around as a result.
Review URL: http://codereview.chromium.org/6608 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3527 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/SConscript1
-rw-r--r--chrome/browser/browser.vcproj4
-rw-r--r--chrome/browser/render_view_host.cc21
-rw-r--r--chrome/browser/render_view_host.h2
-rw-r--r--chrome/browser/render_view_host_delegate.h47
-rw-r--r--chrome/browser/render_widget_helper.cc14
-rw-r--r--chrome/browser/render_widget_helper.h6
-rw-r--r--chrome/browser/render_widget_host_view.h12
-rw-r--r--chrome/browser/render_widget_host_view_win.cc23
-rw-r--r--chrome/browser/render_widget_host_view_win.h4
-rw-r--r--chrome/browser/resource_message_filter.cc16
-rw-r--r--chrome/browser/resource_message_filter.h4
-rw-r--r--chrome/browser/web_contents.cc113
-rw-r--r--chrome/browser/web_contents.h16
-rw-r--r--chrome/browser/web_contents_unittest.cc50
-rw-r--r--chrome/browser/web_contents_view.cc47
-rw-r--r--chrome/browser/web_contents_view.h59
-rw-r--r--chrome/browser/web_contents_view_win.cc104
-rw-r--r--chrome/browser/web_contents_view_win.h15
-rw-r--r--chrome/common/render_messages_internal.h6
-rw-r--r--chrome/renderer/render_view.cc4
21 files changed, 363 insertions, 205 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 ------------------------------------------------------------
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 1b28898..beaa3bf 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -462,11 +462,11 @@ IPC_END_MESSAGES(View)
// These are messages sent from the renderer to the browser process.
IPC_BEGIN_MESSAGES(ViewHost, 2)
- // Sent by the renderer when it is creating a new view. The browser creates
+ // Sent by the renderer when it is creating a new window. The browser creates
// a tab for it and responds with a ViewMsg_CreatingNew_ACK. If route_id is
// MSG_ROUTING_NONE, the view couldn't be created. modal_dialog_event is set
// by the browser when a modal dialog is shown.
- IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_CreateView,
+ IPC_SYNC_MESSAGE_CONTROL2_2(ViewHostMsg_CreateWindow,
int /* opener_id */,
bool /* user_gesture */,
int /* route_id */,
@@ -481,7 +481,7 @@ IPC_BEGIN_MESSAGES(ViewHost, 2)
// These two messages are sent as a result of the above two, in the browser
// process, from RenderWidgetHelper to RenderViewHost.
- IPC_MESSAGE_ROUTED2(ViewHostMsg_CreateViewWithRoute,
+ IPC_MESSAGE_ROUTED2(ViewHostMsg_CreateWindowWithRoute,
int /* route_id */,
HANDLE /* modal_dialog_event */)
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 528120b..48f1a4c 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1676,8 +1676,8 @@ WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
int32 routing_id = MSG_ROUTING_NONE;
HANDLE modal_dialog_event = NULL;
bool result = RenderThread::current()->Send(
- new ViewHostMsg_CreateView(routing_id_, user_gesture, &routing_id,
- &modal_dialog_event));
+ new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id,
+ &modal_dialog_event));
if (routing_id == MSG_ROUTING_NONE) {
DCHECK(modal_dialog_event == NULL);
return NULL;