summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tab_contents
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-06 18:45:56 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-06 18:45:56 +0000
commit7b9627d188d04b224f972fae709e7cb4f61ae504 (patch)
tree4d37368f881c9dae023e5172013e87f0b7c58676 /chrome/browser/tab_contents
parent72baf67602ab1dbf95c34a5d8301e0ac5f8b8b41 (diff)
downloadchromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.zip
chromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.tar.gz
chromium_src-7b9627d188d04b224f972fae709e7cb4f61ae504.tar.bz2
Render a "sad tab" on tab crash.
Uses the NotificationRegistrar to notice TAB_CONTENTS_[DIS]CONNECTED events. When it disconnects, add a SadTabGtk to the TabContentsView. Delete it when the tab contents reconnects. BUG=http://www.crbug.com/11081 TEST=Open http://about:crash. Verify that the sad tab renders properly. Navigate to another page to make sure the SadTabGtk is correctly replaced with a new RenderWidgetHostViewGtk. Review URL: http://codereview.chromium.org/111003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15435 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tab_contents')
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.cc62
-rw-r--r--chrome/browser/tab_contents/tab_contents_view_gtk.h21
2 files changed, 65 insertions, 18 deletions
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
index 9c82b47..a55c8fe 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc
@@ -11,6 +11,7 @@
#include "base/gfx/point.h"
#include "base/gfx/rect.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
+#include "chrome/browser/gtk/sad_tab_gtk.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_factory.h"
#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
@@ -18,6 +19,8 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/common/gtk_util.h"
+#include "chrome/common/notification_source.h"
+#include "chrome/common/notification_type.h"
namespace {
@@ -62,8 +65,11 @@ TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents)
: TabContentsView(tab_contents),
- vbox_(gtk_vbox_new(FALSE, 0)),
- content_view_(NULL) {
+ vbox_(gtk_vbox_new(FALSE, 0)) {
+ registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED,
+ Source<TabContents>(tab_contents));
+ registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED,
+ Source<TabContents>(tab_contents));
}
TabContentsViewGtk::~TabContentsViewGtk() {
@@ -89,19 +95,19 @@ RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget(
RenderWidgetHostViewGtk* view =
new RenderWidgetHostViewGtk(render_widget_host);
view->InitAsChild();
- content_view_ = view->native_view();
- g_signal_connect(content_view_, "focus",
+ gfx::NativeView content_view = view->native_view();
+ g_signal_connect(content_view, "focus",
G_CALLBACK(OnFocus), tab_contents());
- g_signal_connect(view->native_view(), "leave-notify-event",
+ g_signal_connect(content_view, "leave-notify-event",
G_CALLBACK(OnLeaveNotify), tab_contents());
- g_signal_connect(view->native_view(), "motion-notify-event",
+ g_signal_connect(content_view, "motion-notify-event",
G_CALLBACK(OnMouseMove), tab_contents());
- gtk_widget_add_events(view->native_view(), GDK_LEAVE_NOTIFY_MASK |
+ gtk_widget_add_events(content_view, GDK_LEAVE_NOTIFY_MASK |
GDK_POINTER_MOTION_MASK);
- g_signal_connect(view->native_view(), "button-press-event",
+ g_signal_connect(content_view, "button-press-event",
G_CALLBACK(OnMouseDown), this);
gfx::RemoveAllChildren(vbox_.get());
- gtk_box_pack_start(GTK_BOX(vbox_.get()), content_view_, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox_.get()), content_view, TRUE, TRUE, 0);
return view;
}
@@ -110,9 +116,12 @@ gfx::NativeView TabContentsViewGtk::GetNativeView() const {
}
gfx::NativeView TabContentsViewGtk::GetContentNativeView() const {
- return content_view_;
+ if (!tab_contents()->render_widget_host_view())
+ return NULL;
+ return tab_contents()->render_widget_host_view()->GetPluginNativeView();
}
+
gfx::NativeWindow TabContentsViewGtk::GetTopLevelNativeWindow() const {
GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
return window ? GTK_WINDOW(window) : NULL;
@@ -135,12 +144,13 @@ void TabContentsViewGtk::OnContentsDestroy() {
void TabContentsViewGtk::SetPageTitle(const std::wstring& title) {
// Set the window name to include the page title so it's easier to spot
// when debugging (e.g. via xwininfo -tree).
- if (content_view_ && content_view_->window)
- gdk_window_set_title(content_view_->window, WideToUTF8(title).c_str());
+ gfx::NativeView content_view = GetContentNativeView();
+ if (content_view && content_view->window)
+ gdk_window_set_title(content_view->window, WideToUTF8(title).c_str());
}
void TabContentsViewGtk::Invalidate() {
- NOTIMPLEMENTED();
+ gtk_widget_queue_draw(sad_tab_->widget());
}
void TabContentsViewGtk::SizeContents(const gfx::Size& size) {
@@ -173,7 +183,7 @@ void TabContentsViewGtk::SetInitialFocus() {
if (tab_contents()->FocusLocationBarByDefault())
tab_contents()->delegate()->SetFocusToLocationBar();
else
- gtk_widget_grab_focus(content_view_);
+ gtk_widget_grab_focus(GetContentNativeView());
}
void TabContentsViewGtk::StoreFocus() {
@@ -224,6 +234,30 @@ void TabContentsViewGtk::OnFindReply(int request_id,
NOTIMPLEMENTED();
}
+void TabContentsViewGtk::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::TAB_CONTENTS_CONNECTED: {
+ // No need to remove the SadTabGtk's widget from the container since
+ // the new RenderWidgetHostViewGtk instance already removed all the
+ // vbox's children.
+ sad_tab_.reset();
+ break;
+ }
+ case NotificationType::TAB_CONTENTS_DISCONNECTED: {
+ sad_tab_.reset(new SadTabGtk);
+ gtk_box_pack_start(
+ GTK_BOX(vbox_.get()), sad_tab_->widget(), TRUE, TRUE, 0);
+ gtk_widget_show(sad_tab_->widget());
+ break;
+ }
+ default:
+ NOTREACHED() << "Got a notification we didn't register for.";
+ break;
+ }
+}
+
void TabContentsViewGtk::ShowContextMenu(const ContextMenuParams& params) {
context_menu_.reset(new RenderViewContextMenuGtk(tab_contents(), params,
last_mouse_down_time_));
diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h
index 6d24598..4137f67 100644
--- a/chrome/browser/tab_contents/tab_contents_view_gtk.h
+++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h
@@ -7,11 +7,15 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
#include "chrome/common/owned_widget_gtk.h"
class RenderViewContextMenuGtk;
+class SadTabGtk;
-class TabContentsViewGtk : public TabContentsView {
+class TabContentsViewGtk : public TabContentsView,
+ public NotificationObserver {
public:
// The corresponding TabContents is passed in the constructor, and manages our
// lifetime. This doesn't need to be the case, but is this way currently
@@ -55,6 +59,13 @@ class TabContentsViewGtk : public TabContentsView {
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update);
+
+ // NotificationObserver implementation ---------------------------------------
+
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
// We keep track of the timestamp of the latest mousedown event.
static gboolean OnMouseDown(GtkWidget* widget,
@@ -63,9 +74,6 @@ class TabContentsViewGtk : public TabContentsView {
// The native widget for the tab.
OwnedWidgetGtk vbox_;
- // The native widget for the contents of the tab. We do not own this widget.
- GtkWidget* content_view_;
-
// The context menu is reset every time we show it, but we keep a pointer to
// between uses so that it won't go out of scope before we're done with it.
scoped_ptr<RenderViewContextMenuGtk> context_menu_;
@@ -74,6 +82,11 @@ class TabContentsViewGtk : public TabContentsView {
// show context menus.
guint32 last_mouse_down_time_;
+ // Used to get notifications about renderers coming and going.
+ NotificationRegistrar registrar_;
+
+ scoped_ptr<SadTabGtk> sad_tab_;
+
DISALLOW_COPY_AND_ASSIGN(TabContentsViewGtk);
};