summaryrefslogtreecommitdiffstats
path: root/chrome/browser/chromeos
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 22:17:56 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-07 22:17:56 +0000
commit57d49a213c0b00a6c3fcbb283c5a1cdb4a3b7dd1 (patch)
treeb138699c41dd118751d3422ad3c5df9d9134ad86 /chrome/browser/chromeos
parentba051e315ca1c305a46484f2c8f282b3ec149e7a (diff)
downloadchromium_src-57d49a213c0b00a6c3fcbb283c5a1cdb4a3b7dd1.zip
chromium_src-57d49a213c0b00a6c3fcbb283c5a1cdb4a3b7dd1.tar.gz
chromium_src-57d49a213c0b00a6c3fcbb283c5a1cdb4a3b7dd1.tar.bz2
Makes MainMenu a singleton and loaded 5 seconds after startup. This is
done so that we can show the menu quickly. This is a hack. If the menu remains html we'll pull the html into Chrome and won't need this. This is just for a better prototype experience. BUG=24147 TEST=make sure the main menu still works. Review URL: http://codereview.chromium.org/271004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28321 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
-rw-r--r--chrome/browser/chromeos/main_menu.cc89
-rw-r--r--chrome/browser/chromeos/main_menu.h47
2 files changed, 102 insertions, 34 deletions
diff --git a/chrome/browser/chromeos/main_menu.cc b/chrome/browser/chromeos/main_menu.cc
index 2f585b4..b2bb239 100644
--- a/chrome/browser/chromeos/main_menu.cc
+++ b/chrome/browser/chromeos/main_menu.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/string_util.h"
+#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_factory.h"
@@ -92,24 +93,31 @@ static GURL GetMenuURL() {
// static
void MainMenu::Show(Browser* browser) {
- (new MainMenu(browser))->ShowImpl();
+ MainMenu::Get()->ShowImpl(browser);
+}
+
+// static
+void MainMenu::ScheduleCreation() {
+ MessageLoop::current()->PostDelayedTask(FROM_HERE, new LoadTask(), 5000);
}
MainMenu::~MainMenu() {
- popup_->Close();
- menu_rvh_->Shutdown();
+ // NOTE: we leak the menu_rvh_ and popup_ as by the time we get here the
+ // message loop and notification services have been shutdown.
+ // TODO(sky); fix this.
+ // menu_rvh_->Shutdown();
+ // popup_->CloseNow();
}
-MainMenu::MainMenu(Browser* browser)
- : browser_(browser),
+MainMenu::MainMenu()
+ : browser_(NULL),
popup_(NULL),
site_instance_(NULL),
menu_rvh_(NULL),
rwhv_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)) {
-}
-
-void MainMenu::ShowImpl() {
+ ALLOW_THIS_IN_INITIALIZER_LIST(tab_contents_delegate_(this)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
+ has_shown_(false) {
SkBitmap* drop_down_image = ResourceBundle::GetSharedInstance().
GetBitmapNamed(IDR_MAIN_MENU_BUTTON_DROP_DOWN);
@@ -130,8 +138,10 @@ void MainMenu::ShowImpl() {
views::Background::CreateBackgroundPainter(true, painter));
GURL menu_url(GetMenuURL());
- site_instance_ = SiteInstance::CreateSiteInstanceForURL(browser_->profile(),
- menu_url);
+ DCHECK(BrowserList::begin() != BrowserList::end());
+ // TODO(sky): this shouldn't pick a random profile to use.
+ site_instance_ = SiteInstance::CreateSiteInstanceForURL(
+ (*BrowserList::begin())->profile(), menu_url);
menu_rvh_ = new RenderViewHost(site_instance_, this, MSG_ROUTING_NONE);
rwhv_ = new RenderWidgetHostViewGtk(menu_rvh_);
@@ -143,12 +153,29 @@ void MainMenu::ShowImpl() {
rwhv_size.width(), rwhv_size.height());
rwhv_->SetSize(rwhv_size);
menu_rvh_->NavigateToURL(menu_url);
- menu_popup->Show();
+}
+
+// static
+MainMenu* MainMenu::Get() {
+ return Singleton<MainMenu>::get();
+}
+
+void MainMenu::ShowImpl(Browser* browser) {
+ Cleanup();
+
+ browser_ = browser;
+
+ popup_->Show();
GtkWidget* rwhv_widget = rwhv_->GetNativeView();
- gtk_widget_realize(rwhv_widget);
- g_signal_connect(rwhv_widget, "button-press-event",
- G_CALLBACK(CallButtonPressEvent), this);
+
+ if (!has_shown_) {
+ has_shown_ = true;
+ gtk_widget_realize(rwhv_widget);
+ g_signal_connect(rwhv_widget, "button-press-event",
+ G_CALLBACK(CallButtonPressEvent), this);
+ }
+
// Do a mouse grab on the renderer widget host view's widget so that we can
// close the popup if the user clicks anywhere else. And do a keyboard
// grab so that we get all key events.
@@ -160,16 +187,22 @@ void MainMenu::ShowImpl() {
gdk_keyboard_grab(rwhv_widget->window, FALSE, GDK_CURRENT_TIME);
}
-void MainMenu::Delete(bool now) {
+void MainMenu::Hide() {
gdk_keyboard_ungrab(GDK_CURRENT_TIME);
gdk_pointer_ungrab(GDK_CURRENT_TIME);
- // Hide the popup immediately. We don't close it as it contains the
- // renderwidgethostview, which hasn't been shutdown yet.
+
popup_->Hide();
- if (now)
- delete this;
- else
- MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+
+ // The stack may have pending_contents_ on it. Delay deleting the
+ // pending_contents_ as TabContents doesn't deal well with being deleted
+ // while on the stack.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(&MainMenu::Cleanup));
+}
+
+void MainMenu::Cleanup() {
+ pending_contents_.reset(NULL);
+ method_factory_.RevokeAll();
}
// static
@@ -186,7 +219,7 @@ gboolean MainMenu::OnButtonPressEvent(GtkWidget* widget,
event->y >= widget->allocation.height) {
// The user clicked outside the bounds of the menu, delete the main which
// results in closing it.
- Delete(true);
+ Hide();
}
return FALSE;
}
@@ -227,7 +260,7 @@ void MainMenu::ShowCreatedWindow(int route_id,
browser_->GetSelectedTabContents()->AddNewContents(
pending_contents_.release(), disposition, initial_pos, user_gesture,
creator_url);
- Delete(false);
+ Hide();
}
}
@@ -239,5 +272,11 @@ void MainMenu::TabContentsDelegateImpl::OpenURLFromTab(
PageTransition::Type transition) {
menu_->browser_->OpenURL(url, referrer, NEW_FOREGROUND_TAB,
PageTransition::LINK);
- menu_->Delete(true);
+ menu_->Hide();
+}
+
+// LoadTask -------------------------------------------------------------------
+
+void MainMenu::LoadTask::Run() {
+ MainMenu::Get();
}
diff --git a/chrome/browser/chromeos/main_menu.h b/chrome/browser/chromeos/main_menu.h
index e1f7a5f..2d896fc 100644
--- a/chrome/browser/chromeos/main_menu.h
+++ b/chrome/browser/chromeos/main_menu.h
@@ -8,6 +8,8 @@
#include <gtk/gtk.h>
#include "base/scoped_ptr.h"
+#include "base/singleton.h"
+#include "base/task.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/tab_contents/render_view_host_delegate_helper.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
@@ -39,18 +41,34 @@ class WidgetGtk;
// When a new url is opened, or the user clicks outsides the bounds of the
// widget the menu is closed.
//
-// MainMenu manages its own lifetime. In some cases deletion is delayed because
-// the callers can't deal with being deleted while servicing a message from
-// the renderer.
+// MainMenu manages its own lifetime and currently creates one instance for
+// the life of the browser. This is done to make sure we have the html page
+// loaded when the user clicks on it.
class MainMenu : public RenderViewHostDelegate,
public RenderViewHostDelegate::View {
public:
// Shows the menu.
static void Show(Browser* browser);
+ // Schedules creation of the shared MainMenu.
+ static void ScheduleCreation();
+
~MainMenu();
private:
+ friend struct DefaultSingletonTraits<MainMenu>;
+
+ // Task used to ask for the MainMenu instance. This is scheduled from
+ // ScheduleCreation.
+ class LoadTask : public Task {
+ public:
+ LoadTask() {}
+ virtual void Run();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LoadTask);
+ };
+
// TabContentsDelegate and RenderViewHostDelegate::View have some methods
// in common (with differing signatures). The TabContentsDelegate methods are
// implemented by this class.
@@ -87,14 +105,20 @@ class MainMenu : public RenderViewHostDelegate,
friend class TabContentsDelegateImpl;
- explicit MainMenu(Browser* browser);
+ MainMenu();
+
+ // Returns the single MainMenu instance.
+ static MainMenu* Get();
+
+ // Shows the menu for the specified browser.
+ void ShowImpl(Browser* browser);
- void ShowImpl();
+ // Hides the menu.
+ void Hide();
- // Does cleanup before deletion. If |now| is true delete is invoked
- // immediately, otherwise deletion occurs after a delay. See description
- // above class as to why we need to delay deletion in some situations.
- void Delete(bool now);
+ // Cleans up state. This is invoked before showing and after a delay when
+ // hidden.
+ void Cleanup();
// Callback from button presses on the render widget host view. Clicks
// outside the widget resulting in closing the menu.
@@ -164,6 +188,11 @@ class MainMenu : public RenderViewHostDelegate,
// TabContents created when the user clicks a link.
scoped_ptr<TabContents> pending_contents_;
+ ScopedRunnableMethodFactory<MainMenu> method_factory_;
+
+ // True if the popup has ever been shown.
+ bool has_shown_;
+
DISALLOW_COPY_AND_ASSIGN(MainMenu);
};