diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 03:30:22 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-04 03:30:22 +0000 |
commit | 59560e0ba999d5edc33453d4a0fbf44831025817 (patch) | |
tree | f365944f6f0eca593a28747a7fed4caf169578fb /chrome/browser | |
parent | 4d2868972ff25746d39ecea58e88480ae0463145 (diff) | |
download | chromium_src-59560e0ba999d5edc33453d4a0fbf44831025817.zip chromium_src-59560e0ba999d5edc33453d4a0fbf44831025817.tar.gz chromium_src-59560e0ba999d5edc33453d4a0fbf44831025817.tar.bz2 |
Move download shelf from per-tab to per-window. Also disable auto-hiding of
the shelf.
BUG=9025
TEST=Download file in one tab, open new tab, and check that download shelf is
still open. Also try the shelf's close button and the "show all downloads"
link. When saving a file, the download animation should not show up.
Review URL: http://codereview.chromium.org/115740
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
33 files changed, 392 insertions, 408 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index c2e0877..7fce063 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -24,6 +24,7 @@ #include "chrome/browser/browser_window.h" #include "chrome/browser/dom_operation_notification_details.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/download/download_shelf.h" #include "chrome/browser/find_bar.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/find_notification_details.h" @@ -1082,6 +1083,7 @@ void AutomationProvider::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(AutomationMsg_WindowTitle, GetWindowTitle) IPC_MESSAGE_HANDLER(AutomationMsg_SetEnableExtensionAutomation, SetEnableExtensionAutomation) + IPC_MESSAGE_HANDLER(AutomationMsg_SetShelfVisibility, SetShelfVisibility) IPC_END_MESSAGE_MAP() } @@ -1956,11 +1958,27 @@ void AutomationProvider::ExecuteJavascript(int handle, void AutomationProvider::GetShelfVisibility(int handle, bool* visible) { *visible = false; - TabContents* tab_contents = GetTabContentsForHandle(handle, NULL); - if (tab_contents) - *visible = tab_contents->IsDownloadShelfVisible(); + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + *visible = browser->window()->IsDownloadShelfVisible(); + } + } +} + +void AutomationProvider::SetShelfVisibility(int handle, bool visible) { + if (browser_tracker_->ContainsHandle(handle)) { + Browser* browser = browser_tracker_->GetResource(handle); + if (browser) { + if (visible) + browser->window()->GetDownloadShelf()->Show(); + else + browser->window()->GetDownloadShelf()->Close(); + } + } } + void AutomationProvider::GetConstrainedWindowCount(int handle, int* count) { *count = -1; // -1 is the error code if (tab_tracker_->ContainsHandle(handle)) { diff --git a/chrome/browser/automation/automation_provider.h b/chrome/browser/automation/automation_provider.h index 1506868..8673bed 100644 --- a/chrome/browser/automation/automation_provider.h +++ b/chrome/browser/automation/automation_provider.h @@ -215,6 +215,7 @@ class AutomationProvider : public base::RefCounted<AutomationProvider>, const std::wstring& script, IPC::Message* reply_message); void GetShelfVisibility(int handle, bool* visible); + void SetShelfVisibility(int handle, bool visible); void SetFilteredInet(const IPC::Message& message, bool enabled); void SetProxyConfig(const std::string& new_proxy_config); diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 92c8ab6..fe99bdd 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -18,7 +18,10 @@ #include "chrome/browser/character_encoding.h" #include "chrome/browser/debugger/debugger_host.h" #include "chrome/browser/debugger/devtools_manager.h" +#include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/download/download_shelf.h" +#include "chrome/browser/download/download_started_animation.h" #include "chrome/browser/find_bar.h" #include "chrome/browser/find_bar_controller.h" #include "chrome/browser/location_bar.h" @@ -42,6 +45,7 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/page_transition_types.h" +#include "chrome/common/platform_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "chrome/common/url_constants.h" @@ -1153,6 +1157,25 @@ void Browser::OpenHelpTab() { false, NULL); } +void Browser::OnStartDownload(DownloadItem* download) { + if (!window()) + return; + + // GetDownloadShelf creates the download shelf if it was not yet created. + window()->GetDownloadShelf()->AddDownload(new DownloadItemModel(download)); + +// TODO(port): port for mac. +#if defined(OS_WIN) || defined(OS_LINUX) + // Don't show the animation for "Save file" downloads. + if (download->total_bytes() > 0) { + TabContents* current_tab = GetSelectedTabContents(); + // We make this check for the case of minimized windows, unit tests, etc. + if (platform_util::IsVisible(current_tab->GetNativeView())) + DownloadStartedAnimation::Show(current_tab); + } +#endif +} + /////////////////////////////////////////////////////////////////////////////// // static diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index b2950fd..789c9ef 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -381,6 +381,9 @@ class Browser : public TabStripModelDelegate, void OpenAboutChromeDialog(); void OpenHelpTab(); + virtual void OnStartDownload(DownloadItem* download); + virtual void UpdateDownloadShelfVisibility(bool visible); + ///////////////////////////////////////////////////////////////////////////// static void RegisterPrefs(PrefService* prefs); @@ -481,7 +484,6 @@ class Browser : public TabStripModelDelegate, // is the mouse leaving the view. virtual void ContentsMouseEvent(TabContents* source, bool motion); virtual void UpdateTargetURL(TabContents* source, const GURL& url); - virtual void UpdateDownloadShelfVisibility(bool visible); virtual void ContentsZoomChange(bool zoom_in); virtual bool IsApplication() const; diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h index 3ce7097..743cc94 100644 --- a/chrome/browser/browser_window.h +++ b/chrome/browser/browser_window.h @@ -10,6 +10,8 @@ class Browser; class BrowserList; class BrowserWindowTesting; +class DownloadItem; +class DownloadShelf; class FindBar; class GURL; class LocationBar; @@ -143,6 +145,12 @@ class BrowserWindow { // |already_bookmarked| is true if the url is already bookmarked. virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked) = 0; + // Whether or not the shelf view is visible. + virtual bool IsDownloadShelfVisible() const = 0; + + // Returns the DownloadShelf. + virtual DownloadShelf* GetDownloadShelf() = 0; + // Shows the Report a Bug dialog box. virtual void ShowReportBugDialog() = 0; diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index 4cec480..69b9715 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -57,6 +57,8 @@ class BrowserWindowCocoa : public BrowserWindow, virtual void ShowAboutChromeDialog(); virtual void ShowBookmarkManager(); virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked); + virtual bool IsDownloadShelfVisible() const; + virtual DownloadShelf* GetDownloadShelf(); virtual void ShowReportBugDialog(); virtual void ShowClearBrowsingDataDialog(); virtual void ShowImportDialog(); @@ -86,6 +88,12 @@ class BrowserWindowCocoa : public BrowserWindow, NSWindow* window_; // weak, owned by controller Browser* browser_; // weak, owned by controller BrowserWindowController* controller_; // weak, owns us + + // Data for shelves and stuff ------------------------------------------------ + // FIXME(thakis): This should probably in the controller on OS X. + + // The download shelf view (view at the bottom of the page). + scoped_ptr<DownloadShelf> download_shelf_; }; #endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_ diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 429c0be..d052f61 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -10,15 +10,20 @@ #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/clear_browsing_data_controller.h" #include "chrome/browser/browser.h" +#include "chrome/browser/download/download_shelf.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" +#include "chrome/common/temp_scaffolding_stubs.h" #include "chrome/browser/profile.h" BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser, BrowserWindowController* controller, NSWindow* window) - : window_(window), browser_(browser), controller_(controller) { + : window_(window), + browser_(browser), + controller_(controller), + download_shelf_() { // This pref applies to all windows, so all must watch for it. registrar_.Add(this, NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, NotificationService::AllSources()); @@ -182,6 +187,18 @@ void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url, NOTIMPLEMENTED(); } +bool BrowserWindowCocoa::IsDownloadShelfVisible() const { + return download_shelf_ != NULL && download_shelf_->IsShowing(); +} + +DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() { + NOTIMPLEMENTED(); + if (!download_shelf_.get()) { + download_shelf_.reset(new DownloadShelfMac(browser_)); + } + return download_shelf_.get(); +} + void BrowserWindowCocoa::ShowReportBugDialog() { NOTIMPLEMENTED(); } diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc index b871540..7be3411 100644 --- a/chrome/browser/download/download_file.cc +++ b/chrome/browser/download/download_file.cc @@ -536,17 +536,18 @@ void DownloadFileManager::OnShowDownloadInShell(const FilePath& full_path) { void DownloadFileManager::OnOpenDownloadInShell(const FilePath& full_path, const GURL& url, gfx::NativeView parent_window) { - DCHECK(MessageLoop::current() == file_loop_); - #if defined(OS_WIN) - if (NULL != parent_window) { - win_util::SaferOpenItemViaShell(parent_window, L"", full_path, - UTF8ToWide(url.spec())); - return; - } + DCHECK(MessageLoop::current() == file_loop_); + if (NULL != parent_window) { + win_util::SaferOpenItemViaShell(parent_window, L"", full_path, + UTF8ToWide(url.spec())); + } else { + win_util::OpenItemViaShell(full_path); + } +#else + // TODO(port) implement me. + NOTIMPLEMENTED(); #endif - - platform_util::OpenItem(full_path); } // The DownloadManager in the UI thread has provided a final name for the diff --git a/chrome/browser/download/download_shelf.cc b/chrome/browser/download/download_shelf.cc index 6962a3e..0b468c4 100644 --- a/chrome/browser/download/download_shelf.cc +++ b/chrome/browser/download/download_shelf.cc @@ -6,11 +6,11 @@ #include "app/l10n_util.h" #include "base/file_util.h" +#include "chrome/browser/browser.h" #include "chrome/browser/dom_ui/downloads_ui.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/url_constants.h" #include "grit/generated_resources.h" @@ -22,17 +22,11 @@ // DownloadShelf --------------------------------------------------------------- void DownloadShelf::ShowAllDownloads() { - Profile* profile = tab_contents_->profile(); + Profile* profile = browser_->profile(); if (profile) UserMetrics::RecordAction(L"ShowDownloads", profile); - tab_contents_->OpenURL(GURL(chrome::kChromeUIDownloadsURL), GURL(), - SINGLETON_TAB, PageTransition::AUTO_BOOKMARK); -} - -void DownloadShelf::ChangeTabContents(TabContents* old_contents, - TabContents* new_contents) { - DCHECK(old_contents == tab_contents_); - tab_contents_ = new_contents; + browser_->OpenURL(GURL(chrome::kChromeUIDownloadsURL), GURL(), + NEW_FOREGROUND_TAB, PageTransition::AUTO_BOOKMARK); } // DownloadShelfContextMenu ---------------------------------------------------- diff --git a/chrome/browser/download/download_shelf.h b/chrome/browser/download/download_shelf.h index 1b455c0..1ad0b71 100644 --- a/chrome/browser/download/download_shelf.h +++ b/chrome/browser/download/download_shelf.h @@ -7,47 +7,48 @@ #include <string> +#include "base/logging.h" #include "base/basictypes.h" class BaseDownloadItemModel; +class Browser; class DownloadItem; -class TabContents; // DownloadShelf is an interface for platform-specific download shelves to // implement. It also contains some shared logic. This class should not be // instantiated directly, but rather created via a call to Create(). +// It is a view object. class DownloadShelf { public: - explicit DownloadShelf(TabContents* tab_contents) - : tab_contents_(tab_contents) { } + explicit DownloadShelf(Browser* browser) + : browser_(browser) { DCHECK(browser_); } virtual ~DownloadShelf() { } - // Creates a platform-specific DownloadShelf, passing ownership to the caller. - static DownloadShelf* Create(TabContents* tab_contents); - // A new download has started, so add it to our shelf. This object will - // take ownership of |download_model|. + // take ownership of |download_model|. Also make the shelf visible. virtual void AddDownload(BaseDownloadItemModel* download_model) = 0; // Invoked when the user clicks the 'show all downloads' link button. void ShowAllDownloads(); - // Invoked when the download shelf is migrated from one tab contents to a new - // one. - void ChangeTabContents(TabContents* old_contents, TabContents* new_contents); - // The browser view needs to know when we are going away to properly return // the resize corner size to WebKit so that we don't draw on top of it. - // This returns the showing state of our animation which is set to false at - // the beginning Show and true at the beginning of a Hide. + // This returns the showing state of our animation which is set to true at + // the beginning Show and false at the beginning of a Hide. virtual bool IsShowing() const = 0; // Returns whether the download shelf is showing the close animation. virtual bool IsClosing() const = 0; + // Opens the shelf. + virtual void Show() = 0; + + // Closes the shelf. + virtual void Close() = 0; + protected: - TabContents* tab_contents_; + Browser* browser_; private: DISALLOW_COPY_AND_ASSIGN(DownloadShelf); diff --git a/chrome/browser/download/download_uitest.cc b/chrome/browser/download/download_uitest.cc index 78a3683..8f7eb99 100644 --- a/chrome/browser/download/download_uitest.cc +++ b/chrome/browser/download/download_uitest.cc @@ -131,9 +131,7 @@ class DownloadTest : public UITest { // TODO(tc): check download status text // Make sure the download shelf is showing. - scoped_refptr<TabProxy> dl_tab(window->GetTab(0)); - ASSERT_TRUE(dl_tab.get()); - EXPECT_TRUE(WaitForDownloadShelfVisible(dl_tab.get())); + EXPECT_TRUE(WaitForDownloadShelfVisible(window.get())); } FilePath filename; @@ -170,9 +168,9 @@ TEST_F(DownloadTest, DownloadMimeType) { CleanUpDownload(file); - scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); - ASSERT_TRUE(tab_proxy.get()); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab_proxy.get())); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); } // Access a file with a viewable mime-type, verify that a download @@ -196,9 +194,9 @@ TEST_F(DownloadTest, NoDownload) { if (file_util::PathExists(file_path)) ASSERT_TRUE(file_util::Delete(file_path, false)); - scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); - ASSERT_TRUE(tab_proxy.get()); - EXPECT_FALSE(WaitForDownloadShelfVisible(tab_proxy.get())); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + EXPECT_FALSE(WaitForDownloadShelfVisible(browser.get())); } // Download a 0-size file with a content-disposition header, verify that the @@ -218,12 +216,54 @@ TEST_F(DownloadTest, ContentDisposition) { CleanUpDownload(download_file, file); - // Ensure the download shelf is visible on the current tab. - scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); - ASSERT_TRUE(tab_proxy.get()); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab_proxy.get())); + // Ensure the download shelf is visible on the window. + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); } +// Test that the download shelf is per-window by starting a download in one +// tab, opening a second tab, closing the shelf, going back to the first tab, +// and checking that the shelf is closed. +TEST_F(DownloadTest, PerWindowShelf) { + FilePath file(FILE_PATH_LITERAL("download-test3.gif")); + FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif")); + + EXPECT_EQ(1, GetTabCount()); + + NavigateToURL(URLRequestMockHTTPJob::GetMockUrl(file.ToWStringHack())); + WaitUntilTabCount(1); + + // Wait until the file is downloaded. + PlatformThread::Sleep(action_timeout_ms()); + + CleanUpDownload(download_file, file); + + // Ensure the download shelf is visible on the window. + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); + + // Open a second tab + browser->AppendTab(GURL("")); + WaitUntilTabCount(2); + + // Hide shelf + browser->SetShelfVisible(false); + EXPECT_TRUE(WaitForDownloadShelfInvisible(browser.get())); + + // Go to first tab + EXPECT_TRUE(browser->ActivateTab(0)); + int tab_count; + EXPECT_TRUE(browser->GetTabCount(&tab_count)); + ASSERT_EQ(2, tab_count); + + bool shelf_visible; + EXPECT_TRUE(browser->IsShelfVisible(&shelf_visible)); + ASSERT_FALSE(shelf_visible); +} + + // UnknownSize and KnownSize are tests which depend on // URLRequestSlowDownloadJob to serve content in a certain way. Data will be // sent in two chunks where the first chunk is 35K and the second chunk is 10K. diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc index 645346b..cd23fc2 100644 --- a/chrome/browser/download/save_package.cc +++ b/chrome/browser/download/save_package.cc @@ -252,9 +252,7 @@ bool SavePackage::Init() { FilePath(), Time::Now(), 0, -1, -1, false); download_->set_manager(tab_contents_->profile()->GetDownloadManager()); #if !defined(OS_MACOSX) - DownloadShelf* shelf = tab_contents_->GetDownloadShelf(true); - shelf->AddDownload(new SavePageModel(this, download_)); - tab_contents_->SetDownloadShelfVisible(true); + tab_contents_->OnStartDownload(download_); #else // TODO(port): Create a download shelf for mac. NOTIMPLEMENTED(); diff --git a/chrome/browser/download/save_page_uitest.cc b/chrome/browser/download/save_page_uitest.cc index 4562d20..840a9f0 100644 --- a/chrome/browser/download/save_page_uitest.cc +++ b/chrome/browser/download/save_page_uitest.cc @@ -85,7 +85,8 @@ TEST_F(SavePageTest, SaveHTMLOnly) { EXPECT_TRUE(tab->SavePage(full_file_name.ToWStringHack(), dir.ToWStringHack(), SavePackage::SAVE_AS_ONLY_HTML)); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab.get())); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); CheckFile(full_file_name, FilePath::FromWStringHack(UTF8ToWide(file_name)), true); @@ -105,7 +106,8 @@ TEST_F(SavePageTest, SaveCompleteHTML) { EXPECT_TRUE(tab->SavePage(full_file_name.ToWStringHack(), dir.ToWStringHack(), SavePackage::SAVE_AS_COMPLETE_HTML)); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab.get())); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); CheckFile(dir.AppendASCII("1.png"), FilePath(FILE_PATH_LITERAL("1.png")), true); @@ -128,7 +130,8 @@ TEST_F(SavePageTest, NoSave) { EXPECT_FALSE(tab->SavePage(full_file_name.ToWStringHack(), dir.ToWStringHack(), SavePackage::SAVE_AS_ONLY_HTML)); - EXPECT_FALSE(WaitForDownloadShelfVisible(tab.get())); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + EXPECT_FALSE(WaitForDownloadShelfVisible(browser.get())); } TEST_F(SavePageTest, FilenameFromPageTitle) { @@ -148,7 +151,7 @@ TEST_F(SavePageTest, FilenameFromPageTitle) { scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); automation()->SavePackageShouldPromptUser(false); EXPECT_TRUE(browser->RunCommandAsync(IDC_SAVE_PAGE)); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab.get())); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); automation()->SavePackageShouldPromptUser(true); CheckFile(dir.AppendASCII("1.png"), FilePath(FILE_PATH_LITERAL("1.png")), @@ -180,7 +183,7 @@ TEST_F(SavePageTest, CleanFilenameFromPageTitle) { scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); automation()->SavePackageShouldPromptUser(false); EXPECT_TRUE(browser->RunCommandAsync(IDC_SAVE_PAGE)); - EXPECT_TRUE(WaitForDownloadShelfVisible(tab.get())); + EXPECT_TRUE(WaitForDownloadShelfVisible(browser.get())); automation()->SavePackageShouldPromptUser(true); CheckFile(full_file_name, FilePath::FromWStringHack(UTF8ToWide(file_name)), diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 5c090d6..f4b86f2 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -18,10 +18,13 @@ #include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" +#include "chrome/browser/download/download_item_model.h" +#include "chrome/browser/download/download_manager.h" #include "chrome/browser/gtk/about_chrome_dialog.h" #include "chrome/browser/gtk/bookmark_bar_gtk.h" #include "chrome/browser/gtk/browser_toolbar_gtk.h" #include "chrome/browser/gtk/clear_browsing_data_dialog_gtk.h" +#include "chrome/browser/gtk/download_shelf_gtk.h" #include "chrome/browser/gtk/go_button_gtk.h" #include "chrome/browser/gtk/import_dialog_gtk.h" #include "chrome/browser/gtk/infobar_container_gtk.h" @@ -566,6 +569,17 @@ void BrowserWindowGtk::ShowBookmarkBubble(const GURL& url, toolbar_->star()->ShowStarBubble(url, !already_bookmarked); } +bool BrowserWindowGtk::IsDownloadShelfVisible() const { + return download_shelf_.get() && download_shelf_->IsShowing(); +} + +DownloadShelf* BrowserWindowGtk::GetDownloadShelf() { + if (!download_shelf_.get()) + download_shelf_.reset(new DownloadShelfGtk(browser_.get(), + render_area_vbox_)); + return download_shelf_.get(); +} + void BrowserWindowGtk::ShowReportBugDialog() { NOTIMPLEMENTED(); } @@ -604,11 +618,12 @@ void BrowserWindowGtk::UserChangedTheme() { } int BrowserWindowGtk::GetExtraRenderViewHeight() const { - // The download shelf is controlled by its TabContents, so we don't have to - // worry about it here. int sum = infobar_container_->TotalHeightOfClosingBars(); if (bookmark_bar_->IsClosing()) sum += bookmark_bar_->GetHeight(); + if (download_shelf_.get() && download_shelf_->IsClosing()) { + sum += download_shelf_->GetHeight(); + } return sum; } diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index 8e6dee5..4e5f067ad 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -19,6 +19,7 @@ class BookmarkBarGtk; class BrowserToolbarGtk; +class DownloadShelfGtk; class FindBarGtk; class InfoBarContainerGtk; class LocationBar; @@ -71,6 +72,8 @@ class BrowserWindowGtk : public BrowserWindow, virtual void ShowAboutChromeDialog(); virtual void ShowBookmarkManager(); virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked); + virtual bool IsDownloadShelfVisible() const; + virtual DownloadShelf* GetDownloadShelf(); virtual void ShowReportBugDialog(); virtual void ShowClearBrowsingDataDialog(); virtual void ShowImportDialog(); @@ -136,6 +139,9 @@ class BrowserWindowGtk : public BrowserWindow, scoped_ptr<Browser> browser_; + // The download shelf view (view at the bottom of the page). + scoped_ptr<DownloadShelfGtk> download_shelf_; + private: // Sets the default size for the window and the the way the user is allowed to // resize it. diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc index 55ef572..22f2b3a 100644 --- a/chrome/browser/gtk/download_item_gtk.cc +++ b/chrome/browser/gtk/download_item_gtk.cc @@ -177,18 +177,18 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, InitNineBoxes(); LoadIcon(); - body_ = gtk_button_new(); - gtk_widget_set_app_paintable(body_, TRUE); - g_signal_connect(body_, "expose-event", + body_.Own(gtk_button_new()); + gtk_widget_set_app_paintable(body_.get(), TRUE); + g_signal_connect(body_.get(), "expose-event", G_CALLBACK(OnExpose), this); - g_signal_connect(body_, "clicked", + g_signal_connect(body_.get(), "clicked", G_CALLBACK(OnClick), this); - GTK_WIDGET_UNSET_FLAGS(body_, GTK_CAN_FOCUS); + GTK_WIDGET_UNSET_FLAGS(body_.get(), GTK_CAN_FOCUS); // Remove internal padding on the button. GtkRcStyle* no_padding_style = gtk_rc_style_new(); no_padding_style->xthickness = 0; no_padding_style->ythickness = 0; - gtk_widget_modify_style(body_, no_padding_style); + gtk_widget_modify_style(body_.get(), no_padding_style); g_object_unref(no_padding_style); name_label_ = gtk_label_new(NULL); @@ -221,18 +221,18 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, // We use a GtkFixed because we don't want it to have its own window. // This choice of widget is not critically important though. - progress_area_ = gtk_fixed_new(); - gtk_widget_set_size_request(progress_area_, + progress_area_.Own(gtk_fixed_new()); + gtk_widget_set_size_request(progress_area_.get(), download_util::kSmallProgressIconSize, download_util::kSmallProgressIconSize); - gtk_widget_set_app_paintable(progress_area_, TRUE); - g_signal_connect(progress_area_, "expose-event", + gtk_widget_set_app_paintable(progress_area_.get(), TRUE); + g_signal_connect(progress_area_.get(), "expose-event", G_CALLBACK(OnProgressAreaExpose), this); // Put the download progress icon on the left of the labels. GtkWidget* body_hbox = gtk_hbox_new(FALSE, 0); - gtk_container_add(GTK_CONTAINER(body_), body_hbox); - gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(body_.get()), body_hbox); + gtk_box_pack_start(GTK_BOX(body_hbox), progress_area_.get(), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(body_hbox), text_stack, TRUE, TRUE, 0); menu_button_ = gtk_button_new(); @@ -247,12 +247,12 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, gtk_widget_set_size_request(menu_button_, kMenuButtonWidth, 0); GtkWidget* shelf_hbox = parent_shelf->GetHBox(); - hbox_ = gtk_hbox_new(FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox_), body_, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(hbox_), menu_button_, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(shelf_hbox), hbox_, FALSE, FALSE, 0); + hbox_.Own(gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start(GTK_BOX(hbox_.get()), body_.get(), FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox_.get()), menu_button_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(shelf_hbox), hbox_.get(), FALSE, FALSE, 0); // Insert as the leftmost item. - gtk_box_reorder_child(GTK_BOX(shelf_hbox), hbox_, 1); + gtk_box_reorder_child(GTK_BOX(shelf_hbox), hbox_.get(), 1); resize_handler_id_ = g_signal_connect(G_OBJECT(shelf_hbox), "size-allocate", G_CALLBACK(OnShelfResized), this); @@ -261,11 +261,11 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, new_item_animation_.reset(new SlideAnimation(this)); new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs); - gtk_widget_show_all(hbox_); + gtk_widget_show_all(hbox_.get()); if (IsDangerous()) { // Hide the download item components for now. - gtk_widget_hide(body_); + gtk_widget_hide(body_.get()); gtk_widget_hide(menu_button_); // Create an hbox to hold it all. @@ -327,7 +327,7 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, gtk_alignment_set_padding(GTK_ALIGNMENT(dangerous_prompt_), 0, 0, kDangerousElementPadding, kDangerousElementPadding); gtk_container_add(GTK_CONTAINER(dangerous_prompt_), dangerous_hbox_); - gtk_box_pack_start(GTK_BOX(hbox_), dangerous_prompt_, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox_.get()), dangerous_prompt_, FALSE, FALSE, 0); gtk_widget_set_app_paintable(dangerous_prompt_, TRUE); g_signal_connect(dangerous_prompt_, "expose-event", G_CALLBACK(OnDangerousPromptExpose), this); @@ -346,9 +346,23 @@ DownloadItemGtk::DownloadItemGtk(DownloadShelfGtk* parent_shelf, DownloadItemGtk::~DownloadItemGtk() { StopDownloadProgress(); - g_signal_handler_disconnect(parent_shelf_->GetHBox(), resize_handler_id_); - gtk_widget_destroy(hbox_); + + // If the top-level window was already destroyed, the signal handler was + // already disconnected. Disconnect if that's not the case. + if (g_signal_handler_find(parent_shelf_->GetHBox(), + G_SIGNAL_MATCH_ID, + resize_handler_id_, + 0, + NULL, + NULL, + NULL) != 0) { + g_signal_handler_disconnect(parent_shelf_->GetHBox(), resize_handler_id_); + } get_download()->RemoveObserver(this); + + hbox_.Destroy(); + progress_area_.Destroy(); + body_.Destroy(); } void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) { @@ -357,7 +371,7 @@ void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) { if (dangerous_prompt_ != NULL && download->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED) { // We have been approved. - gtk_widget_show_all(hbox_); + gtk_widget_show_all(hbox_.get()); gtk_widget_destroy(dangerous_prompt_); dangerous_prompt_ = NULL; } @@ -407,7 +421,7 @@ void DownloadItemGtk::OnDownloadUpdated(DownloadItem* download) { void DownloadItemGtk::AnimationProgressed(const Animation* animation) { if (animation == complete_animation_.get()) { - gtk_widget_queue_draw(progress_area_); + gtk_widget_queue_draw(progress_area_.get()); } else { if (IsDangerous()) { int progress = (dangerous_hbox_full_width_ - @@ -424,7 +438,7 @@ void DownloadItemGtk::AnimationProgressed(const Animation* animation) { download_util::kSmallProgressIconSize) * new_item_animation_->GetCurrentValue())); showing_width = std::max(showing_width, kMinDownloadItemWidth); - gtk_widget_set_size_request(body_, showing_width, -1); + gtk_widget_set_size_request(body_.get(), showing_width, -1); } } } @@ -443,7 +457,7 @@ void DownloadItemGtk::UpdateDownloadProgress() { progress_angle_ = (progress_angle_ + download_util::kUnknownIncrementDegrees) % download_util::kMaxDegrees; - gtk_widget_queue_draw(progress_area_); + gtk_widget_queue_draw(progress_area_.get()); } void DownloadItemGtk::StartDownloadProgress() { @@ -463,7 +477,7 @@ void DownloadItemGtk::StopDownloadProgress() { void DownloadItemGtk::OnLoadIconComplete(IconManager::Handle handle, SkBitmap* icon_bitmap) { icon_ = icon_bitmap; - gtk_widget_queue_draw(progress_area_); + gtk_widget_queue_draw(progress_area_.get()); } void DownloadItemGtk::LoadIcon() { @@ -543,7 +557,7 @@ gboolean DownloadItemGtk::OnExpose(GtkWidget* widget, GdkEventExpose* e, DownloadItemGtk* download_item) { NineBox* nine_box = NULL; // If true, this widget is |body_|, otherwise it is |menu_button_|. - bool is_body = widget == download_item->body_; + bool is_body = widget == download_item->body_.get(); if (GTK_WIDGET_STATE(widget) == GTK_STATE_PRELIGHT) nine_box = is_body ? body_nine_box_prelight_ : menu_nine_box_prelight_; else if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE) @@ -641,11 +655,11 @@ gboolean DownloadItemGtk::OnMenuButtonPressEvent(GtkWidget* button, void DownloadItemGtk::OnShelfResized(GtkWidget *widget, GtkAllocation *allocation, DownloadItemGtk* item) { - if (item->hbox_->allocation.x + item->hbox_->allocation.width > + if (item->hbox_.get()->allocation.x + item->hbox_.get()->allocation.width > item->bounding_widget_->allocation.x) - gtk_widget_hide(item->hbox_); + gtk_widget_hide(item->hbox_.get()); else - gtk_widget_show(item->hbox_); + gtk_widget_show(item->hbox_.get()); } // static diff --git a/chrome/browser/gtk/download_item_gtk.h b/chrome/browser/gtk/download_item_gtk.h index 13680cd..e2fbf10 100644 --- a/chrome/browser/gtk/download_item_gtk.h +++ b/chrome/browser/gtk/download_item_gtk.h @@ -11,6 +11,7 @@ #include "base/scoped_ptr.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/icon_manager.h" +#include "chrome/common/owned_widget_gtk.h" class BaseDownloadItemModel; class DownloadShelfContextMenuGtk; @@ -26,8 +27,7 @@ class DownloadItemGtk : public DownloadItem::Observer, DownloadItemGtk(DownloadShelfGtk* parent_shelf, BaseDownloadItemModel* download_item_model); - // We put |hbox_| in |parent_shelf| and rely on |parent_shelf| recursively - // destroying its children. Hence we do nothing in the destructor. + // Destroys all widgets belonging to this DownloadItemGtk. ~DownloadItemGtk(); // DownloadItem::Observer implementation. @@ -109,11 +109,11 @@ class DownloadItemGtk : public DownloadItem::Observer, DownloadShelfGtk* parent_shelf_; // The widget that contains the body and menu dropdown. - GtkWidget* hbox_; + OwnedWidgetGtk hbox_; // The widget that contains the name of the download and the progress // animation. - GtkWidget* body_; + OwnedWidgetGtk body_; // The GtkLabel that holds the download title text. GtkWidget* name_label_; @@ -130,7 +130,7 @@ class DownloadItemGtk : public DownloadItem::Observer, // The widget that contains the animation progress and the file's icon // (as well as the complete animation). - GtkWidget* progress_area_; + OwnedWidgetGtk progress_area_; // In degrees. Only used for downloads with no known total size. int progress_angle_; diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc index 005536e..ab5e4c3 100644 --- a/chrome/browser/gtk/download_shelf_gtk.cc +++ b/chrome/browser/gtk/download_shelf_gtk.cc @@ -7,8 +7,10 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/gfx/gtk_util.h" +#include "chrome/browser/browser.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_util.h" +#include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/download_item_gtk.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" @@ -47,13 +49,8 @@ const int kShelfAnimationDurationMs = 120; } // namespace -// static -DownloadShelf* DownloadShelf::Create(TabContents* tab_contents) { - return new DownloadShelfGtk(tab_contents); -} - -DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) - : DownloadShelf(tab_contents), +DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent) + : DownloadShelf(browser), is_showing_(false) { // Logically, the shelf is a vbox that contains two children: a one pixel // tall event box, which serves as the top border, and an hbox, which holds @@ -69,8 +66,8 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) gtk_widget_modify_bg(top_border, GTK_STATE_NORMAL, &kBorderColor); // Create |hbox_|. - hbox_ = gtk_hbox_new(FALSE, kDownloadItemPadding); - gtk_widget_set_size_request(hbox_, -1, kDownloadItemHeight); + hbox_.Own(gtk_hbox_new(FALSE, kDownloadItemPadding)); + gtk_widget_set_size_request(hbox_.get(), -1, kDownloadItemHeight); // Get the padding and background color for |hbox_| right. GtkWidget* padding = gtk_alignment_new(0, 0, 1, 1); @@ -79,7 +76,7 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) kTopBottomPadding - 1, kTopBottomPadding, kLeftPadding, kRightPadding); GtkWidget* padding_bg = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(padding_bg), padding); - gtk_container_add(GTK_CONTAINER(padding), hbox_); + gtk_container_add(GTK_CONTAINER(padding), hbox_.get()); gtk_widget_modify_bg(padding_bg, GTK_STATE_NORMAL, &kBackgroundColor); shelf_.Own(gtk_vbox_new(FALSE, 0)); @@ -88,7 +85,7 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) // Create and pack the close button. close_button_.reset(CustomDrawButton::CloseButton()); - gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0); + gtk_util::CenterWidgetInHBox(hbox_.get(), close_button_->widget(), true, 0); g_signal_connect(close_button_->widget(), "clicked", G_CALLBACK(OnButtonClick), this); @@ -112,16 +109,16 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) link_hbox_ = gtk_hbox_new(FALSE, 5); gtk_util::CenterWidgetInHBox(link_hbox_, download_image, false, 0); gtk_util::CenterWidgetInHBox(link_hbox_, link_button, false, 0); - gtk_box_pack_end(GTK_BOX(hbox_), link_hbox_, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(hbox_.get()), link_hbox_, FALSE, FALSE, 0); slide_widget_.reset(new SlideAnimatorGtk(shelf_.get(), SlideAnimatorGtk::UP, kShelfAnimationDurationMs, false, NULL)); gtk_widget_show_all(shelf_.get()); - // Stick ourselves at the bottom of the parent tab contents. - GtkWidget* parent_contents = tab_contents->GetNativeView(); - gtk_box_pack_end(GTK_BOX(parent_contents), slide_widget_->widget(), + + // Stick ourselves at the bottom of the parent browser. + gtk_box_pack_end(GTK_BOX(parent), slide_widget_->widget(), FALSE, FALSE, 0); slide_widget_->Open(); } @@ -133,11 +130,12 @@ DownloadShelfGtk::~DownloadShelfGtk() { } shelf_.Destroy(); + hbox_.Destroy(); } void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) { download_items_.push_back(new DownloadItemGtk(this, download_model_)); - slide_widget_->Open(); + Show(); } bool DownloadShelfGtk::IsShowing() const { @@ -148,6 +146,21 @@ bool DownloadShelfGtk::IsClosing() const { return slide_widget_->IsClosing(); } +void DownloadShelfGtk::Show() { + slide_widget_->Open(); +} + +void DownloadShelfGtk::Close() { + slide_widget_->Close(); + + // TODO(estade): Remove. The status bubble should query its window instead. + browser_->UpdateDownloadShelfVisibility(false); +} + +int DownloadShelfGtk::GetHeight() const { + return slide_widget_->widget()->allocation.height; +} + void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) { DCHECK(download_item); std::vector<DownloadItemGtk*>::iterator i = @@ -157,7 +170,9 @@ void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) { delete download_item; if (download_items_.empty()) { slide_widget_->CloseWithoutAnimation(); - tab_contents_->SetDownloadShelfVisible(false); + + // TODO(estade): Remove. The status bubble should query its window instead. + browser_->UpdateDownloadShelfVisibility(false); } } @@ -166,15 +181,14 @@ GtkWidget* DownloadShelfGtk::GetRightBoundingWidget() const { } GtkWidget* DownloadShelfGtk::GetHBox() const { - return hbox_; + return hbox_.get(); } // static void DownloadShelfGtk::OnButtonClick(GtkWidget* button, DownloadShelfGtk* shelf) { if (button == shelf->close_button_->widget()) { - shelf->slide_widget_->Close(); - shelf->tab_contents_->SetDownloadShelfVisible(false); + shelf->Close(); } else { // The link button was clicked. shelf->ShowAllDownloads(); diff --git a/chrome/browser/gtk/download_shelf_gtk.h b/chrome/browser/gtk/download_shelf_gtk.h index 4ed81b7..afafd27 100644 --- a/chrome/browser/gtk/download_shelf_gtk.h +++ b/chrome/browser/gtk/download_shelf_gtk.h @@ -9,18 +9,20 @@ #include <vector> +#include "base/gfx/native_widget_types.h" #include "base/scoped_ptr.h" #include "chrome/browser/download/download_shelf.h" #include "chrome/common/owned_widget_gtk.h" class BaseDownloadItemModel; +class Browser; class CustomDrawButton; class DownloadItemGtk; class SlideAnimatorGtk; class DownloadShelfGtk : public DownloadShelf { public: - explicit DownloadShelfGtk(TabContents* tab_contents); + explicit DownloadShelfGtk(Browser* browser, gfx::NativeView view); ~DownloadShelfGtk(); @@ -28,6 +30,11 @@ class DownloadShelfGtk : public DownloadShelf { virtual void AddDownload(BaseDownloadItemModel* download_model); virtual bool IsShowing() const; virtual bool IsClosing() const; + virtual void Show(); + virtual void Close(); + + // Returns the current height of the shelf. + int GetHeight() const; private: // Remove |download_item| from the download shelf and delete it. @@ -45,7 +52,7 @@ class DownloadShelfGtk : public DownloadShelf { scoped_ptr<SlideAnimatorGtk> slide_widget_; // |hbox_| holds the download items and buttons of the shelf. - GtkWidget* hbox_; + OwnedWidgetGtk hbox_; // |shelf_| is the second highest level widget. See the constructor // for an explanation of the widget layout. diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index c2a3be6..87920c3 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -91,9 +91,6 @@ TabRendererGtk::TabImage TabRendererGtk::tab_alpha = {0}; TabRendererGtk::TabImage TabRendererGtk::tab_hover_ = {0}; gfx::Font* TabRendererGtk::title_font_ = NULL; int TabRendererGtk::title_font_height_ = 0; -SkBitmap* TabRendererGtk::download_icon_ = NULL; -int TabRendererGtk::download_icon_width_ = 0; -int TabRendererGtk::download_icon_height_ = 0; int TabRendererGtk::close_button_width_ = 0; int TabRendererGtk::close_button_height_ = 0; @@ -173,7 +170,6 @@ class TabRendererGtk::FavIconCrashAnimation : public Animation, TabRendererGtk::TabRendererGtk() : showing_icon_(false), - showing_download_icon_(false), showing_close_button_(false), fav_icon_hiding_offset_(0), should_display_crashed_favicon_(false), @@ -200,7 +196,6 @@ void TabRendererGtk::UpdateData(TabContents* contents, bool loading_only) { if (!loading_only) { data_.title = UTF16ToWideHack(contents->GetTitle()); data_.off_the_record = contents->profile()->IsOffTheRecord(); - data_.show_download_icon = contents->IsDownloadShelfVisible(); data_.crashed = contents->is_crashed(); data_.favicon = contents->GetFavIcon(); } @@ -303,10 +298,6 @@ void TabRendererGtk::LoadTabImages() { close_button_width_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->width(); close_button_height_ = rb.GetBitmapNamed(IDR_TAB_CLOSE)->height(); - - download_icon_ = rb.GetBitmapNamed(IDR_DOWNLOAD_ICON); - download_icon_width_ = download_icon_->width(); - download_icon_height_ = download_icon_->height(); } void TabRendererGtk::SetBounds(const gfx::Rect& bounds) { @@ -378,10 +369,8 @@ void TabRendererGtk::Paint(gfx::Canvas* canvas) { // See if the model changes whether the icons should be painted. const bool show_icon = ShouldShowIcon(); - const bool show_download_icon = data_.show_download_icon; const bool show_close_button = ShouldShowCloseBox(); if (show_icon != showing_icon_ || - show_download_icon != showing_download_icon_ || show_close_button != showing_close_button_) Layout(); @@ -418,11 +407,6 @@ void TabRendererGtk::Paint(gfx::Canvas* canvas) { } } - if (show_download_icon) { - canvas->DrawBitmapInt(*download_icon_, - download_icon_bounds_.x(), download_icon_bounds_.y()); - } - // Paint the Title. std::wstring title = data_.title; if (title.empty()) { @@ -475,15 +459,6 @@ void TabRendererGtk::Layout() { favicon_bounds_.SetRect(local_bounds.x(), local_bounds.y(), 0, 0); } - // Size the download icon. - showing_download_icon_ = data_.show_download_icon; - if (showing_download_icon_) { - int icon_top = kTopPadding + (content_height - download_icon_height_) / 2; - download_icon_bounds_.SetRect(local_bounds.width() - download_icon_width_, - icon_top, download_icon_width_, - download_icon_height_); - } - // Size the Close button. showing_close_button_ = ShouldShowCloseBox(); if (showing_close_button_) { @@ -518,8 +493,6 @@ void TabRendererGtk::Layout() { } else { title_width = std::max(local_bounds.width() - title_left, 0); } - if (data_.show_download_icon) - title_width = std::max(title_width - download_icon_width_, 0); title_bounds_.SetRect(title_left, title_top, title_width, title_font_height_); // TODO(jhawkins): Handle RTL layout. diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.h b/chrome/browser/gtk/tabs/tab_renderer_gtk.h index 4f555a1..990081f 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.h +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.h @@ -161,7 +161,6 @@ class TabRendererGtk : public AnimationDelegate { bool crashed; bool off_the_record; bool show_icon; - bool show_download_icon; }; // TODO(jhawkins): Move into TabResources class. @@ -238,7 +237,6 @@ class TabRendererGtk : public AnimationDelegate { // The bounds of various sections of the display. gfx::Rect favicon_bounds_; - gfx::Rect download_icon_bounds_; gfx::Rect title_bounds_; gfx::Rect close_button_bounds_; @@ -252,10 +250,6 @@ class TabRendererGtk : public AnimationDelegate { static gfx::Font* title_font_; static int title_font_height_; - static SkBitmap* download_icon_; - static int download_icon_width_; - static int download_icon_height_; - static int close_button_width_; static int close_button_height_; @@ -266,9 +260,6 @@ class TabRendererGtk : public AnimationDelegate { // changes and layout appropriately. bool showing_icon_; - // Whether we are showing the download icon. Comes from the model. - bool showing_download_icon_; - // Whether we are showing the close button. It is cached so that we can // detect when it changes and layout appropriately. bool showing_close_button_; diff --git a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc index f9d51d7..09a8833 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host_uitest.cc @@ -68,11 +68,8 @@ TEST_F(ResourceDispatcherTest, SniffNoContentTypeNoData) { // Make sure the download shelf is not showing. scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - scoped_refptr<TabProxy> dl_tab(browser->GetTab(0)); - ASSERT_TRUE(dl_tab.get()); - bool visible = false; - ASSERT_TRUE(dl_tab->IsShelfVisible(&visible)); + ASSERT_TRUE(browser->IsShelfVisible(&visible)); EXPECT_FALSE(visible); } @@ -155,10 +152,12 @@ TEST_F(ResourceDispatcherTest, SyncXMLHttpRequest_DuringUnload) { EXPECT_FALSE(timed_out); // Check that the new page got loaded, and that no download was triggered. - bool shelf_is_visible = false; EXPECT_TRUE(tab->GetTabTitle(&tab_title)); - EXPECT_TRUE(tab->IsShelfVisible(&shelf_is_visible)); EXPECT_EQ(L"Title Of Awesomeness", tab_title); + + bool shelf_is_visible = false; + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + EXPECT_TRUE(browser->IsShelfVisible(&shelf_is_visible)); EXPECT_FALSE(shelf_is_visible); } diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 3e15f10..4bc4366 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -21,8 +21,6 @@ #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_request_manager.h" -#include "chrome/browser/download/download_shelf.h" -#include "chrome/browser/download/download_started_animation.h" #include "chrome/browser/gears_integration.h" #include "chrome/browser/google_util.h" #include "chrome/browser/hung_renderer_dialog.h" @@ -43,7 +41,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/page_action.h" -#include "chrome/common/platform_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "chrome/common/render_messages.h" @@ -115,10 +112,6 @@ const int kSyncWaitDelay = 40; // contents. const int kJavascriptMessageExpectedDelay = 1000; -// Minimum amount of time in ms that has to elapse since the download shelf was -// shown for us to hide it when navigating away from the current page. -const int kDownloadShelfHideDelay = 5000; - const char kLinkDoctorBaseURL[] = "http://linkhelp.clients.google.com/tbproxy/lh/fixurl"; @@ -235,11 +228,8 @@ TabContents::TabContents(Profile* profile, is_starred_(false), contents_mime_type_(), encoding_(), - download_shelf_(), - shelf_visible_(false), blocked_popups_(NULL), infobar_delegates_(), - last_download_shelf_show_(), find_ui_active_(false), find_op_aborted_(false), current_find_request_id_(find_request_id_counter_++), @@ -926,32 +916,6 @@ bool TabContents::IsBookmarkBarAlwaysVisible() { return false; // Default. } -void TabContents::SetDownloadShelfVisible(bool visible) { - if (shelf_visible_ != visible) { - if (visible) { - // Invoke GetDownloadShelf to force the shelf to be created. - GetDownloadShelf(true); - } - shelf_visible_ = visible; - - NotifyNavigationStateChanged(INVALIDATE_TAB); - - if (delegate()) - delegate()->UpdateDownloadShelfVisibility(visible); - } - - // SetShelfVisible can force-close the shelf, so make sure we lay out - // everything correctly, as if the animation had finished. This doesn't - // matter for showing the shelf, as the show animation will do it. - ToolbarSizeChanged(false); - - if (visible) { - // Always set this value as it reflects the last time the download shelf - // was made visible (even if it was already visible). - last_download_shelf_show_ = base::TimeTicks::Now(); - } -} - void TabContents::ToolbarSizeChanged(bool is_animating) { TabContentsDelegate* d = delegate(); if (d) @@ -964,42 +928,8 @@ void TabContents::OnStartDownload(DownloadItem* download) { // Download in a constrained popup is shown in the tab that opened it. TabContents* tab_contents = delegate()->GetConstrainingContents(this); - // GetDownloadShelf creates the download shelf if it was not yet created. - tab_contents->GetDownloadShelf(true)->AddDownload( - new DownloadItemModel(download)); - tab_contents->SetDownloadShelfVisible(true); - -// TODO(port): port for mac. -#if defined(OS_WIN) || defined(OS_LINUX) - // We make this check for the case of minimized windows, unit tests, etc. - if (platform_util::IsVisible(GetNativeView())) { - DownloadStartedAnimation::Show(tab_contents); - } -#endif -} - -DownloadShelf* TabContents::GetDownloadShelf(bool create) { - if (!download_shelf_.get() && create) - download_shelf_.reset(DownloadShelf::Create(this)); - return download_shelf_.get(); -} - -void TabContents::MigrateShelfFrom(TabContents* tab_contents) { - download_shelf_.reset(tab_contents->GetDownloadShelf(true)); - download_shelf_->ChangeTabContents(tab_contents, this); - tab_contents->ReleaseDownloadShelf(); -} - -void TabContents::ReleaseDownloadShelf() { - download_shelf_.release(); -} - -// static -void TabContents::MigrateShelf(TabContents* from, TabContents* to) { - bool was_shelf_visible = from->IsDownloadShelfVisible(); - if (was_shelf_visible) - to->MigrateShelfFrom(from); - to->SetDownloadShelfVisible(was_shelf_visible); + if (tab_contents && tab_contents->delegate()) + tab_contents->delegate()->OnStartDownload(download); } void TabContents::WillClose(ConstrainedWindow* window) { @@ -1296,27 +1226,6 @@ DOMUI* TabContents::GetDOMUIForCurrentState() { void TabContents::DidNavigateMainFramePostCommit( const NavigationController::LoadCommittedDetails& details, const ViewHostMsg_FrameNavigate_Params& params) { - // Hide the download shelf if all the following conditions are true: - // - there are no active downloads. - // - this is a navigation to a different TLD. - // - at least 5 seconds have elapsed since the download shelf was shown. - // TODO(jcampan): bug 1156075 when user gestures are reliable, they should - // be used to ensure we are hiding only on user initiated - // navigations. - DownloadManager* download_manager = profile()->GetDownloadManager(); - // download_manager can be NULL in unit test context. - if (download_manager && download_manager->in_progress_count() == 0 && - !details.previous_url.is_empty() && - !net::RegistryControlledDomainService::SameDomainOrHost( - details.previous_url, details.entry->url())) { - base::TimeDelta time_delta( - base::TimeTicks::Now() - last_download_shelf_show_); - if (time_delta > - base::TimeDelta::FromMilliseconds(kDownloadShelfHideDelay)) { - SetDownloadShelfVisible(false); - } - } - if (details.is_user_initiated_main_frame_load()) { // Clear the status bubble. This is a workaround for a bug where WebKit // doesn't let us know that the cursor left an element during a diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index c43a919..026cf3d 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -66,7 +66,6 @@ class BlockedPopupContainer; class DOMUI; class DOMUIContents; class DownloadItem; -class DownloadShelf; class LoadNotificationDetails; class PageAction; class PasswordManager; @@ -405,30 +404,12 @@ class TabContents : public PageNavigator, // Returns whether the bookmark bar should be visible. virtual bool IsBookmarkBarAlwaysVisible(); - // Whether or not the shelf view is visible. - virtual void SetDownloadShelfVisible(bool visible); - bool IsDownloadShelfVisible() { return shelf_visible_; } + // Notifies the delegate that a download started. + void OnStartDownload(DownloadItem* download); // Notify our delegate that some of our content has animated. void ToolbarSizeChanged(bool is_animating); - // Displays the download shelf and animation when a download occurs. - void OnStartDownload(DownloadItem* download); - - // Returns the DownloadShelf. If the shelf doesn't exist and |create| is true, - // this function will create the shelf. - DownloadShelf* GetDownloadShelf(bool create); - - // Transfer the shelf view from |tab_contents| to the receiving TabContents. - // |tab_contents| no longer owns the shelf after this call. The shelf is owned - // by the receiving TabContents. - void MigrateShelfFrom(TabContents* tab_contents); - - // Migrate the shelf view between 2 TabContents. This helper function is - // currently called by NavigationController::DiscardPendingEntry. We may - // want to generalize this if we need to migrate some other state. - static void MigrateShelf(TabContents* from, TabContents* to); - // Called when a ConstrainedWindow we own is about to be closed. void WillClose(ConstrainedWindow* window); @@ -641,9 +622,6 @@ class TabContents : public PageNavigator, // determines whether to show itself). bool ShowingBlockedPopupNotification() const; - // Releases the download shelf. This method is used by MigrateShelfFrom. - void ReleaseDownloadShelf(); - // Called by derived classes to indicate that we're no longer waiting for a // response. This won't actually update the throbber, but it will get picked // up at the next animation step if the throbber is going. @@ -992,12 +970,6 @@ class TabContents : public PageNavigator, // Data for shelves and stuff ------------------------------------------------ - // The download shelf view (view at the bottom of the page). - scoped_ptr<DownloadShelf> download_shelf_; - - // Whether the shelf view is visible. - bool shelf_visible_; - // ConstrainedWindow with additional methods for managing blocked // popups. This pointer also goes in |child_windows_| for ownership, // repositioning, etc. @@ -1006,9 +978,6 @@ class TabContents : public PageNavigator, // Delegates for InfoBars associated with this TabContents. std::vector<InfoBarDelegate*> infobar_delegates_; - // The last time that the download shelf was made visible. - base::TimeTicks last_download_shelf_show_; - // Data for find in page ----------------------------------------------------- // TODO(brettw) this should be separated into a helper class. diff --git a/chrome/browser/tab_contents/tab_contents_delegate.h b/chrome/browser/tab_contents/tab_contents_delegate.h index 465877f..da5bd60 100644 --- a/chrome/browser/tab_contents/tab_contents_delegate.h +++ b/chrome/browser/tab_contents/tab_contents_delegate.h @@ -11,6 +11,7 @@ #include "chrome/common/page_transition_types.h" #include "webkit/glue/window_open_disposition.h" +class DownloadItem; class ExtensionFunctionDispatcher; class RenderViewHost; class TabContents; @@ -89,9 +90,6 @@ class TabContentsDelegate { // Notification that the target URL has changed virtual void UpdateTargetURL(TabContents* source, const GURL& url) = 0; - // Notification that the download shelf visibility state has been toggled. - virtual void UpdateDownloadShelfVisibility(bool visible) { } - // Notification that there was a mouse event virtual void ContentsMouseEvent(TabContents* source, bool motion) { } @@ -178,6 +176,9 @@ class TabContentsDelegate { return 0; } + virtual void OnStartDownload(DownloadItem* download) { + } + protected: ~TabContentsDelegate() {} diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index 174b7e7..5103bc0 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -98,12 +98,10 @@ TabContentsView* TabContentsView::Create(TabContents* tab_contents) { TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) : TabContentsView(tab_contents), - vbox_(gtk_vbox_new(FALSE, 0)) { - fixed_ = gtk_fixed_new(); - gtk_box_pack_start(GTK_BOX(vbox_.get()), fixed_, TRUE, TRUE, 0); - g_signal_connect(fixed_, "size-allocate", + fixed_(gtk_fixed_new()) { + g_signal_connect(fixed_.get(), "size-allocate", G_CALLBACK(OnSizeAllocate), this); - gtk_widget_show(fixed_); + gtk_widget_show(fixed_.get()); registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, Source<TabContents>(tab_contents)); registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED, @@ -111,7 +109,7 @@ TabContentsViewGtk::TabContentsViewGtk(TabContents* tab_contents) } TabContentsViewGtk::~TabContentsViewGtk() { - vbox_.Destroy(); + fixed_.Destroy(); } void TabContentsViewGtk::CreateView() { @@ -153,7 +151,7 @@ RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget( } gfx::NativeView TabContentsViewGtk::GetNativeView() const { - return vbox_.get(); + return fixed_.get(); } gfx::NativeView TabContentsViewGtk::GetContentNativeView() const { @@ -175,10 +173,10 @@ void TabContentsViewGtk::GetContainerBounds(gfx::Rect* out) const { // animation. int x = 0; int y = 0; - if (vbox_.get()->window) - gdk_window_get_origin(vbox_.get()->window, &x, &y); - out->SetRect(x + vbox_.get()->allocation.x, y + vbox_.get()->allocation.y, - vbox_.get()->allocation.width, vbox_.get()->allocation.height); + if (fixed_.get()->window) + gdk_window_get_origin(fixed_.get()->window, &x, &y); + out->SetRect(x + fixed_.get()->allocation.x, y + fixed_.get()->allocation.y, + fixed_.get()->allocation.width, fixed_.get()->allocation.height); } void TabContentsViewGtk::OnContentsDestroy() { @@ -304,7 +302,7 @@ void TabContentsViewGtk::StartDragging(const WebDropData& drop_data) { } void TabContentsViewGtk::InsertIntoContentArea(GtkWidget* widget) { - gtk_fixed_put(GTK_FIXED(fixed_), widget, 0, 0); + gtk_fixed_put(GTK_FIXED(fixed_.get()), widget, 0, 0); } gboolean TabContentsViewGtk::OnMouseDown(GtkWidget* widget, @@ -317,9 +315,7 @@ gboolean TabContentsViewGtk::OnSizeAllocate(GtkWidget* widget, GtkAllocation* allocation, TabContentsViewGtk* view) { int width = allocation->width; - DownloadShelf* shelf = view->tab_contents()->GetDownloadShelf(false); - int height = shelf && shelf->IsClosing() ? - widget->parent->allocation.height : allocation->height; + int height = allocation->height; height += view->tab_contents()->delegate()->GetExtraRenderViewHeight(); gfx::Size size(width, height); gtk_container_foreach(GTK_CONTAINER(widget), SetSizeRequest, &size); diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h index 9e6fdc4..b6908ff 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.h +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h @@ -74,12 +74,9 @@ class TabContentsViewGtk : public TabContentsView, GtkAllocation* config, TabContentsViewGtk* view); - // The native widget for the tab. - OwnedWidgetGtk vbox_; - // This container holds the tab's web page views. It is a GtkFixed so that we // can control the size of the web pages. - GtkWidget* fixed_; + OwnedWidgetGtk fixed_; // 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. diff --git a/chrome/browser/views/download_shelf_view.cc b/chrome/browser/views/download_shelf_view.cc index fcf01df..d651548 100644 --- a/chrome/browser/views/download_shelf_view.cc +++ b/chrome/browser/views/download_shelf_view.cc @@ -10,12 +10,13 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/logging.h" +#include "chrome/browser/browser.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/tab_contents/navigation_entry.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/views/download_item_view.h" +#include "chrome/browser/views/frame/browser_view.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "views/background.h" @@ -70,13 +71,9 @@ int CenterPosition(int size, int target_size) { } // namespace -// static -DownloadShelf* DownloadShelf::Create(TabContents* tab_contents) { - return new DownloadShelfView(tab_contents); -} - -DownloadShelfView::DownloadShelfView(TabContents* tab_contents) - : DownloadShelf(tab_contents) { +DownloadShelfView::DownloadShelfView(Browser* browser, BrowserView* parent) + : DownloadShelf(browser), parent_(parent) { + parent->AddChildView(this); Init(); } @@ -105,14 +102,11 @@ void DownloadShelfView::Init() { shelf_animation_.reset(new SlideAnimation(this)); shelf_animation_->SetSlideDuration(kShelfAnimationDurationMs); - shelf_animation_->Show(); - - // The download shelf view is always owned by its tab contents. - SetParentOwned(false); + Show(); } void DownloadShelfView::AddDownloadView(View* view) { - shelf_animation_->Show(); + Show(); DCHECK(view); download_views_.push_back(view); @@ -139,7 +133,7 @@ void DownloadShelfView::RemoveDownloadView(View* view) { RemoveChildView(view); delete view; if (download_views_.empty()) - tab_contents_->SetDownloadShelfVisible(false); + Close(); Layout(); SchedulePaint(); } @@ -182,26 +176,18 @@ void DownloadShelfView::AnimationProgressed(const Animation *animation) { // otherwise leave blank white areas where the shelf was and where the // user's eye is. Thankfully bottom-resizing is a lot faster than // top-resizing. - tab_contents_->ToolbarSizeChanged(shelf_animation_->IsShowing()); + parent_->SelectedTabToolbarSizeChanged(shelf_animation_->IsShowing()); } } void DownloadShelfView::AnimationEnded(const Animation *animation) { if (animation == shelf_animation_.get()) { - tab_contents_->SetDownloadShelfVisible(shelf_animation_->IsShowing()); + if (download_views_.empty()) + parent_->SetDownloadShelfVisible(shelf_animation_->IsShowing()); } } void DownloadShelfView::Layout() { - // When the download shelf is not visible it is not parented to anything, - // which means it is not safe to lay out the controls, so we return early. - // Otherwise, we can have problems when for example the user switches to - // another tab (that doesn't have a download shelf) _before_ the download - // has started and we'll crash when calling SetVisible() below because - // the NativeControlContainer ctor tries to use the Container. - if (!GetWidget()) - return; - // Now that we know we have a parent, we can safely set our theme colors. show_all_view_->SetColor( GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT)); @@ -301,7 +287,7 @@ void DownloadShelfView::LinkActivated(views::Link* source, int event_flags) { } void DownloadShelfView::ButtonPressed(views::Button* button) { - shelf_animation_->Hide(); + Close(); } bool DownloadShelfView::IsShowing() const { @@ -312,3 +298,12 @@ bool DownloadShelfView::IsClosing() const { // TODO(estade): This is never called. For now just return false. return false; } + +void DownloadShelfView::Show() { + shelf_animation_->Show(); +} + +void DownloadShelfView::Close() { + parent_->SetDownloadShelfVisible(false); + shelf_animation_->Hide(); +} diff --git a/chrome/browser/views/download_shelf_view.h b/chrome/browser/views/download_shelf_view.h index 0b722b8..e11d468 100644 --- a/chrome/browser/views/download_shelf_view.h +++ b/chrome/browser/views/download_shelf_view.h @@ -16,7 +16,8 @@ class ImageView; } class BaseDownloadItemModel; -class TabContents; +class Browser; +class BrowserView; class DownloadAnimation; @@ -33,7 +34,7 @@ class DownloadShelfView : public DownloadShelf, public views::LinkController, public AnimationDelegate { public: - explicit DownloadShelfView(TabContents* tab_contents); + explicit DownloadShelfView(Browser* browser, BrowserView* parent); // Implementation of View. virtual gfx::Size GetPreferredSize(); @@ -57,6 +58,8 @@ class DownloadShelfView : public DownloadShelf, virtual void AddDownload(BaseDownloadItemModel* download_model); virtual bool IsShowing() const; virtual bool IsClosing() const; + virtual void Show(); + virtual void Close(); // Removes a specified download view. The supplied view is deleted after // it's removed. @@ -97,6 +100,9 @@ class DownloadShelfView : public DownloadShelf, // deleted by View. views::ImageButton* close_button_; + // The window this shelf belongs to. + BrowserView* parent_; + DISALLOW_COPY_AND_ASSIGN(DownloadShelfView); }; diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 078faac..9d41882 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -300,9 +300,9 @@ BrowserView::BrowserView(Browser* browser) frame_(NULL), browser_(browser), active_bookmark_bar_(NULL), - active_download_shelf_(NULL), tabstrip_(NULL), toolbar_(NULL), + download_shelf_(NULL), infobar_container_(NULL), find_bar_y_(0), contents_container_(NULL), @@ -818,11 +818,8 @@ gfx::Rect BrowserView::GetRootWindowResizerRect() const { // shelf, so we don't want others to do it for us in this case. // Currently, the only visible bottom shelf is the download shelf. // Other tests should be added here if we add more bottom shelves. - TabContents* current_tab = browser_->GetSelectedTabContents(); - if (current_tab && current_tab->IsDownloadShelfVisible()) { - DownloadShelf* download_shelf = current_tab->GetDownloadShelf(true); - if (download_shelf && download_shelf->IsShowing()) - return gfx::Rect(); + if (download_shelf_ && download_shelf_->IsShowing()) { + return gfx::Rect(); } gfx::Rect client_rect = contents_container_->bounds(); @@ -854,6 +851,32 @@ void BrowserView::ShowBookmarkBubble(const GURL& url, bool already_bookmarked) { toolbar_->star_button()->ShowStarBubble(url, !already_bookmarked); } +void BrowserView::SetDownloadShelfVisible(bool visible) { + if (IsDownloadShelfVisible() != visible) { + if (visible) { + // Invoke GetDownloadShelf to force the shelf to be created. + GetDownloadShelf(); + } + + browser_->UpdateDownloadShelfVisibility(visible); + } + + // SetDownloadShelfVisible can force-close the shelf, so make sure we lay out + // everything correctly, as if the animation had finished. This doesn't + // matter for showing the shelf, as the show animation will do it. + SelectedTabToolbarSizeChanged(false); +} + +bool BrowserView::IsDownloadShelfVisible() const { + return download_shelf_ && download_shelf_->IsShowing(); +} + +DownloadShelf* BrowserView::GetDownloadShelf() { + if (!download_shelf_) + download_shelf_ = new DownloadShelfView(browser_.get(), this); + return download_shelf_; +} + void BrowserView::ShowReportBugDialog() { // Retrieve the URL for the current tab (if any) and tell the BugReportView TabContents* current_tab = browser_->GetSelectedTabContents(); @@ -1451,14 +1474,14 @@ void BrowserView::LayoutTabContents(int top, int bottom) { } int BrowserView::LayoutDownloadShelf(int bottom) { - if (active_download_shelf_) { + if (IsDownloadShelfVisible()) { bool visible = browser_->SupportsWindowFeature( Browser::FEATURE_DOWNLOADSHELF); - int height = - visible ? active_download_shelf_->GetPreferredSize().height() : 0; - active_download_shelf_->SetVisible(visible); - active_download_shelf_->SetBounds(0, bottom - height, width(), height); - active_download_shelf_->Layout(); + DCHECK(download_shelf_); + int height = visible ? download_shelf_->GetPreferredSize().height() : 0; + download_shelf_->SetVisible(visible); + download_shelf_->SetBounds(0, bottom - height, width(), height); + download_shelf_->Layout(); bottom -= height; } return bottom; @@ -1514,21 +1537,9 @@ bool BrowserView::MaybeShowInfoBar(TabContents* contents) { return true; } -bool BrowserView::MaybeShowDownloadShelf(TabContents* contents) { - views::View* new_shelf = NULL; - if (contents && contents->IsDownloadShelfVisible()) { - new_shelf = - static_cast<DownloadShelfView*>(contents->GetDownloadShelf(true)); - if (new_shelf != active_download_shelf_) - new_shelf->AddChildView(new ResizeCorner()); - } - return UpdateChildViewAndLayout(new_shelf, &active_download_shelf_); -} - void BrowserView::UpdateUIForContents(TabContents* contents) { bool needs_layout = MaybeShowBookmarkBar(contents); needs_layout |= MaybeShowInfoBar(contents); - needs_layout |= MaybeShowDownloadShelf(contents); if (needs_layout) Layout(); } diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h index f4c0983..98d1e56 100644 --- a/chrome/browser/views/frame/browser_view.h +++ b/chrome/browser/views/frame/browser_view.h @@ -28,6 +28,7 @@ class BookmarkBarView; class Browser; class BrowserBubble; class BrowserToolbarView; +class DownloadShelfView; class EncodingMenuControllerDelegate; class ExtensionShelf; class FullscreenExitBubble; @@ -215,6 +216,9 @@ class BrowserView : public BrowserWindow, virtual void ShowAboutChromeDialog(); virtual void ShowBookmarkManager(); virtual void ShowBookmarkBubble(const GURL& url, bool already_bookmarked); + virtual void SetDownloadShelfVisible(bool visible); + virtual bool IsDownloadShelfVisible() const; + virtual DownloadShelf* GetDownloadShelf(); virtual void ShowReportBugDialog(); virtual void ShowClearBrowsingDataDialog(); virtual void ShowImportDialog(); @@ -317,12 +321,6 @@ class BrowserView : public BrowserWindow, // |contents| can be NULL. bool MaybeShowInfoBar(TabContents* contents); - // Prepare to show a Download Shelf for the specified TabContents. Returns - // true if there is a Download Shelf to show and one is supported for this - // Browser type, and there should be a subsequent re-layout to show it. - // |contents| can be NULL. - bool MaybeShowDownloadShelf(TabContents* contents); - // Updates various optional child Views, e.g. Bookmarks Bar, Info Bar or the // Download Shelf in response to a change notification from the specified // |contents|. |contents| can be NULL. In this case, all optional UI will be @@ -365,7 +363,6 @@ class BrowserView : public BrowserWindow, // active_bookmark_bar_ is either NULL, if the bookmark bar isn't showing, // or is bookmark_bar_view_ if the bookmark bar is showing. views::View* active_bookmark_bar_; - views::View* active_download_shelf_; // The TabStrip. TabStrip* tabstrip_; @@ -376,6 +373,9 @@ class BrowserView : public BrowserWindow, // The Bookmark Bar View for this window. Lazily created. scoped_ptr<BookmarkBarView> bookmark_bar_view_; + // The download shelf view (view at the bottom of the page). + DownloadShelfView* download_shelf_; + // The InfoBarContainer that contains InfoBars for the current tab. InfoBarContainer* infobar_container_; diff --git a/chrome/browser/views/tabs/tab_renderer.cc b/chrome/browser/views/tabs/tab_renderer.cc index c270f20..fefae85 100644 --- a/chrome/browser/views/tabs/tab_renderer.cc +++ b/chrome/browser/views/tabs/tab_renderer.cc @@ -65,9 +65,6 @@ static SkBitmap* crashed_fav_icon = NULL; static int loading_animation_frame_count = 0; static int waiting_animation_frame_count = 0; static int waiting_to_loading_frame_count_ratio = 0; -static SkBitmap* download_icon = NULL; -static int download_icon_width = 0; -static int download_icon_height = 0; TabRenderer::TabImage TabRenderer::tab_alpha = {0}; TabRenderer::TabImage TabRenderer::tab_active = {0}; @@ -138,10 +135,6 @@ void InitResources() { crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON); - download_icon = rb.GetBitmapNamed(IDR_DOWNLOAD_ICON); - download_icon_width = download_icon->width(); - download_icon_height = download_icon->height(); - initialized = true; } } @@ -237,7 +230,6 @@ TabRenderer::TabRenderer() : animation_state_(ANIMATION_NONE), animation_frame_(0), showing_icon_(false), - showing_download_icon_(false), showing_close_button_(false), fav_icon_hiding_offset_(0), crash_animation_(NULL), @@ -286,7 +278,6 @@ void TabRenderer::UpdateData(TabContents* contents, bool loading_only) { if (!loading_only) { data_.title = UTF16ToWideHack(contents->GetTitle()); data_.off_the_record = contents->profile()->IsOffTheRecord(); - data_.show_download_icon = contents->IsDownloadShelfVisible(); data_.crashed = contents->is_crashed(); data_.favicon = contents->GetFavIcon(); } @@ -400,10 +391,8 @@ void TabRenderer::Paint(gfx::Canvas* canvas) { // See if the model changes whether the icons should be painted. const bool show_icon = ShouldShowIcon(); - const bool show_download_icon = data_.show_download_icon; const bool show_close_button = ShouldShowCloseBox(); if (show_icon != showing_icon_ || - show_download_icon != showing_download_icon_ || show_close_button != showing_close_button_) Layout(); @@ -442,11 +431,6 @@ void TabRenderer::Paint(gfx::Canvas* canvas) { } } - if (show_download_icon) { - canvas->DrawBitmapInt(*download_icon, - download_icon_bounds_.x(), download_icon_bounds_.y()); - } - // Paint the Title. std::wstring title = data_.title; if (title.empty()) { @@ -487,14 +471,6 @@ void TabRenderer::Layout() { favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0); } - // Size the download icon. - showing_download_icon_ = data_.show_download_icon; - if (showing_download_icon_) { - int icon_top = kTopPadding + (content_height - download_icon_height) / 2; - download_icon_bounds_.SetRect(lb.width() - download_icon_width, icon_top, - download_icon_width, download_icon_height); - } - // Size the Close button. showing_close_button_ = ShouldShowCloseBox(); if (showing_close_button_) { @@ -530,21 +506,17 @@ void TabRenderer::Layout() { } else { title_width = std::max(lb.width() - title_left, 0); } - if (data_.show_download_icon) - title_width = std::max(title_width - download_icon_width, 0); title_bounds_.SetRect(title_left, title_top, title_width, title_font_height); - // Certain UI elements within the Tab (the favicon, the download icon, etc.) - // are not represented as child Views (which is the preferred method). - // Instead, these UI elements are drawn directly on the canvas from within - // Tab::Paint(). The Tab's child Views (for example, the Tab's close button - // which is a views::Button instance) are automatically mirrored by the - // mirroring infrastructure in views. The elements Tab draws directly - // on the canvas need to be manually mirrored if the View's layout is - // right-to-left. + // Certain UI elements within the Tab (the favicon, etc.) are not represented + // as child Views (which is the preferred method). Instead, these UI elements + // are drawn directly on the canvas from within Tab::Paint(). The Tab's child + // Views (for example, the Tab's close button which is a views::Button + // instance) are automatically mirrored by the mirroring infrastructure in + // views. The elements Tab draws directly on the canvas need to be manually + // mirrored if the View's layout is right-to-left. favicon_bounds_.set_x(MirroredLeftPointForRect(favicon_bounds_)); title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_)); - download_icon_bounds_.set_x(MirroredLeftPointForRect(download_icon_bounds_)); } void TabRenderer::OnMouseEntered(const views::MouseEvent& e) { diff --git a/chrome/browser/views/tabs/tab_renderer.h b/chrome/browser/views/tabs/tab_renderer.h index 26dc4cd..f0785ab 100644 --- a/chrome/browser/views/tabs/tab_renderer.h +++ b/chrome/browser/views/tabs/tab_renderer.h @@ -135,7 +135,6 @@ class TabRenderer : public views::View, // The bounds of various sections of the display. gfx::Rect favicon_bounds_; - gfx::Rect download_icon_bounds_; gfx::Rect title_bounds_; // Current state of the animation. @@ -163,7 +162,6 @@ class TabRenderer : public views::View, bool crashed; bool off_the_record; bool show_icon; - bool show_download_icon; }; TabData data_; @@ -183,9 +181,6 @@ class TabRenderer : public views::View, // changes and layout appropriately. bool showing_icon_; - // Whether we are showing the download icon. Comes from the model. - bool showing_download_icon_; - // Whether we are showing the close button. It is cached so that we can // detect when it changes and layout appropriately. bool showing_close_button_; |