diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:01:26 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-19 22:01:26 +0000 |
commit | fa5c9a0393065b41c2b81fc20e12ff232cafb17b (patch) | |
tree | e23686f952a7e2e16c5954f05b5028ffde30970b /chrome/browser/gtk | |
parent | 12b5d06ea959032da7288b8b2b435adfc2c2cea3 (diff) | |
download | chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.zip chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.tar.gz chromium_src-fa5c9a0393065b41c2b81fc20e12ff232cafb17b.tar.bz2 |
Add a TabContentsContainerGtk to remove the current hack that inserts the
RenderViewHostGtk native_view() into the widget heiarchy.
(Now we're crashing on cross site instance navigation because it
looks like we aren't updating some internal reference to the new renderer.)
Review URL: http://codereview.chromium.org/21517
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10045 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk')
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 61 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 26 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.cc | 112 | ||||
-rw-r--r-- | chrome/browser/gtk/tab_contents_container_gtk.h | 59 |
4 files changed, 238 insertions, 20 deletions
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index a1fa41e..86bbfa4 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -11,6 +11,7 @@ #include "chrome/browser/gtk/nine_box.h" #include "chrome/browser/gtk/browser_toolbar_view_gtk.h" #include "chrome/browser/gtk/status_bubble_gtk.h" +#include "chrome/browser/gtk/tab_contents_container_gtk.h" #include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" #include "chrome/browser/tab_contents/web_contents.h" @@ -57,14 +58,16 @@ gfx::Rect GetInitialWindowBounds(GtkWindow* window) { } // namespace BrowserWindowGtk::BrowserWindowGtk(Browser* browser) - : content_area_(NULL), - browser_(browser), - custom_frame_(false) // TODO(port): make this a pref. -{ + : browser_(browser), + // TODO(port): make this a pref. + custom_frame_(false) { Init(); + browser_->tabstrip_model()->AddObserver(this); } BrowserWindowGtk::~BrowserWindowGtk() { + browser_->tabstrip_model()->RemoveObserver(this); + Close(); } @@ -81,8 +84,8 @@ gboolean BrowserWindowGtk::OnContentAreaExpose(GtkWidget* widget, const int kFramePixels = 2; GdkPixbuf* pixbuf = - gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, // alpha - 8, // bit depth + gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, // alpha + 8, // bit depth widget->allocation.width, BrowserToolbarGtk::kToolbarHeight + kFramePixels); @@ -141,6 +144,9 @@ void BrowserWindowGtk::Init() { toolbar_->Init(browser_->profile()); toolbar_->AddToolbarToBox(vbox_); + contents_container_.reset(new TabContentsContainerGtk()); + contents_container_->AddContainerToBox(vbox_); + // Note that calling this the first time is necessary to get the // proper control layout. // TODO(port): make this a pref. @@ -152,15 +158,6 @@ void BrowserWindowGtk::Init() { } void BrowserWindowGtk::Show() { - // TODO(estade): fix this block. As it stands, it is a temporary hack to get - // the browser displaying something. - if (content_area_ == NULL) { - WebContents* contents = (WebContents*)(browser_->GetTabContentsAt(0)); - content_area_ = ((RenderWidgetHostViewGtk*)contents-> - render_view_host()->view())->native_view(); - gtk_box_pack_start(GTK_BOX(vbox_), content_area_, TRUE, TRUE, 0); - } - gtk_widget_show_all(GTK_WIDGET(window_)); } @@ -318,6 +315,40 @@ void BrowserWindowGtk::ShowHTMLDialog(HtmlDialogContentsDelegate* delegate, NOTIMPLEMENTED(); } +void BrowserWindowGtk::TabDetachedAt(TabContents* contents, int index) { + // We use index here rather than comparing |contents| because by this time + // the model has already removed |contents| from its list, so + // browser_->GetSelectedTabContents() will return NULL or something else. + if (index == browser_->tabstrip_model()->selected_index()) { + // TODO(port): Uncoment this line when we get infobars. + // infobar_container_->ChangeTabContents(NULL); + contents_container_->SetTabContents(NULL); + } +} + +void BrowserWindowGtk::TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture) { + DCHECK(old_contents != new_contents); + + // Update various elements that are interested in knowing the current + // TabContents. + // TOOD(port): Un-comment this line when we get infobars. + // infobar_container_->ChangeTabContents(new_contents); + contents_container_->SetTabContents(new_contents); + + new_contents->DidBecomeSelected(); + + // Update all the UI bits. + UpdateTitleBar(); + toolbar_->SetProfile(new_contents->profile()); + UpdateToolbar(new_contents, true); +} + +void BrowserWindowGtk::TabStripEmpty() { +} + void BrowserWindowGtk::DestroyBrowser() { browser_.reset(); } diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 6ff3ce0..70ed990 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -2,24 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_WINDOW_GTK_H_ -#define CHROME_BROWSER_WINDOW_GTK_H_ +#ifndef CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ +#define CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ #include <gtk/gtk.h> #include "base/gfx/rect.h" #include "base/scoped_ptr.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/tabs/tab_strip_model.h" class BrowserToolbarGtk; class NineBox; class StatusBubbleGtk; +class TabContentsContainerGtk; // An implementation of BrowserWindow for GTK. // Cross-platform code will interact with this object when // it needs to manipulate the window. -class BrowserWindowGtk : public BrowserWindow { +class BrowserWindowGtk : public BrowserWindow, + public TabStripModelObserver { public: explicit BrowserWindowGtk(Browser* browser); virtual ~BrowserWindowGtk(); @@ -64,6 +67,14 @@ class BrowserWindowGtk : public BrowserWindow { virtual void ShowHTMLDialog(HtmlDialogContentsDelegate* delegate, void* parent_window); + // Overridden from TabStripModelObserver: + virtual void TabDetachedAt(TabContents* contents, int index); + virtual void TabSelectedAt(TabContents* old_contents, + TabContents* new_contents, + int index, + bool user_gesture); + virtual void TabStripEmpty(); + void OnBoundsChanged(const gfx::Rect& bounds); void OnStateChanged(GdkWindowState state); @@ -71,7 +82,6 @@ class BrowserWindowGtk : public BrowserWindow { virtual void DestroyBrowser(); GtkWindow* window_; GtkWidget* vbox_; - GtkWidget* content_area_; scoped_ptr<Browser> browser_; @@ -96,11 +106,17 @@ class BrowserWindowGtk : public BrowserWindow { // Whether we're drawing the custom Chrome frame (including title bar). bool custom_frame_; + // The object that manages all of the widgets in the toolbar. scoped_ptr<BrowserToolbarGtk> toolbar_; // The status bubble manager. Always non-NULL. scoped_ptr<StatusBubbleGtk> status_bubble_; + + // A container that manages the GtkWidget*s that are the webpage display + // (along with associated infobars, shelves, and other things that are part + // of the content area). + scoped_ptr<TabContentsContainerGtk> contents_container_; }; -#endif // CHROME_BROWSER_WINDOW_GTK_H_ +#endif // CHROME_BROWSER_GTK_BROWSER_WINDOW_GTK_H_ diff --git a/chrome/browser/gtk/tab_contents_container_gtk.cc b/chrome/browser/gtk/tab_contents_container_gtk.cc new file mode 100644 index 0000000..9f07b66 --- /dev/null +++ b/chrome/browser/gtk/tab_contents_container_gtk.cc @@ -0,0 +1,112 @@ +// Copyright (c) 2009 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/gtk/tab_contents_container_gtk.h" + +#include "base/gfx/native_widget_types.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h" +#include "chrome/common/notification_service.h" + + +TabContentsContainerGtk::TabContentsContainerGtk() + : tab_contents_(NULL), + vbox_(gtk_vbox_new(FALSE, 0)) { +} + +TabContentsContainerGtk::~TabContentsContainerGtk() { + if (tab_contents_) + RemoveObservers(); +} + +void TabContentsContainerGtk::AddContainerToBox(GtkWidget* box) { + gtk_box_pack_start(GTK_BOX(box), vbox_, TRUE, TRUE, 0); +} + +void TabContentsContainerGtk::SetTabContents(TabContents* tab_contents) { + if (tab_contents_) { + gfx::NativeView widget = tab_contents_->GetNativeView(); + if (widget) { + gtk_container_remove(GTK_CONTAINER(vbox_), widget); + } + + tab_contents_->WasHidden(); + + RemoveObservers(); + } + + tab_contents_ = tab_contents; + + // When detaching the last tab of the browser SetTabContents is invoked + // with NULL. Don't attempt to do anything in that case. + if (tab_contents_) { + AddObservers(); + + gfx::NativeView widget = tab_contents_->GetNativeView(); + if (widget) { + gtk_box_pack_start(GTK_BOX(vbox_), widget, TRUE, TRUE, 0); + } + } +} + +void TabContentsContainerGtk::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (type == NotificationType::RENDER_VIEW_HOST_CHANGED) { + RenderViewHostSwitchedDetails* switched_details = + Details<RenderViewHostSwitchedDetails>(details).ptr(); + RenderViewHostChanged(switched_details->old_host, + switched_details->new_host); + } else if (type == NotificationType::TAB_CONTENTS_DESTROYED) { + TabContentsDestroyed(Source<TabContents>(source).ptr()); + } else { + NOTREACHED(); + } +} + +void TabContentsContainerGtk::AddObservers() { + DCHECK(tab_contents_); + if (tab_contents_->AsWebContents()) { + // WebContents can change their RenderViewHost and hence the GtkWidget that + // is shown. I'm not entirely sure that we need to observe this event under + // GTK, but am putting a stub implementation and a comment saying that if + // we crash after that NOTIMPLEMENTED(), we'll need it. + NotificationService::current()->AddObserver( + this, NotificationType::RENDER_VIEW_HOST_CHANGED, + Source<NavigationController>(tab_contents_->controller())); + } + NotificationService::current()->AddObserver( + this, + NotificationType::TAB_CONTENTS_DESTROYED, + Source<TabContents>(tab_contents_)); +} + +void TabContentsContainerGtk::RemoveObservers() { + DCHECK(tab_contents_); + if (tab_contents_->AsWebContents()) { + NotificationService::current()->RemoveObserver( + this, + NotificationType::RENDER_VIEW_HOST_CHANGED, + Source<NavigationController>(tab_contents_->controller())); + } + NotificationService::current()->RemoveObserver( + this, + NotificationType::TAB_CONTENTS_DESTROYED, + Source<TabContents>(tab_contents_)); +} + +void TabContentsContainerGtk::RenderViewHostChanged(RenderViewHost* old_host, + RenderViewHost* new_host) { + // If you find a crash right after this NOTIMPLEMENTED(), we'll need to + // switch out some widgets like in SetTabContents(). + NOTIMPLEMENTED(); +} + +void TabContentsContainerGtk::TabContentsDestroyed(TabContents* contents) { + // Sometimes, a TabContents is destroyed before we know about it. This allows + // us to clean up our state in case this happens. + DCHECK(contents == tab_contents_); + SetTabContents(NULL); +} + diff --git a/chrome/browser/gtk/tab_contents_container_gtk.h b/chrome/browser/gtk/tab_contents_container_gtk.h new file mode 100644 index 0000000..927f1f6 --- /dev/null +++ b/chrome/browser/gtk/tab_contents_container_gtk.h @@ -0,0 +1,59 @@ +// Copyright (c) 2009 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. + +#ifndef CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ +#define CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ + +#include <gtk/gtk.h> + +#include "base/basictypes.h" +#include "chrome/common/notification_observer.h" + +class RenderViewHost; +class TabContents; + +class TabContentsContainerGtk : public NotificationObserver { + public: + TabContentsContainerGtk(); + ~TabContentsContainerGtk(); + + // Inserts our GtkWidget* hierarchy into a GtkBox managed by our owner. + void AddContainerToBox(GtkWidget* widget); + + // Make the specified tab visible. + void SetTabContents(TabContents* tab_contents); + TabContents* GetTabContents() const { return tab_contents_; } + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + // Add or remove observers for events that we care about. + void AddObservers(); + void RemoveObservers(); + + // Called when the RenderViewHost of the hosted TabContents has changed, e.g. + // to show an interstitial page. + void RenderViewHostChanged(RenderViewHost* old_host, + RenderViewHost* new_host); + + // Called when a TabContents is destroyed. This gives us a chance to clean + // up our internal state if the TabContents is somehow destroyed before we + // get notified. + void TabContentsDestroyed(TabContents* contents); + + // The currently visible TabContents. + TabContents* tab_contents_; + + // We keep a GtkVBox which is inserted into this object's owner's GtkWidget + // hierarchy. We then insert and remove WebContents GtkWidgets into this + // vbox_. + GtkWidget* vbox_; + + DISALLOW_EVIL_CONSTRUCTORS(TabContentsContainerGtk); +}; + +#endif // CHROME_BROWSER_GTK_TAB_CONTENTS_CONTAINER_GTK_H__ |