diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-03 16:44:57 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-03 16:44:57 +0000 |
commit | 415ad48ad827f0a88645069f2bb731d497f5f23e (patch) | |
tree | a9efe67f99ae4625badca6c19848487e27bc5dad /chrome/browser/views/blocked_popup_container.cc | |
parent | bd745438c31d1646cfb1e99a419e7b17dc2b90d2 (diff) | |
download | chromium_src-415ad48ad827f0a88645069f2bb731d497f5f23e.zip chromium_src-415ad48ad827f0a88645069f2bb731d497f5f23e.tar.gz chromium_src-415ad48ad827f0a88645069f2bb731d497f5f23e.tar.bz2 |
This is the first of probably several patches trying to clean up the BlockedPopupContainer into something that can be cross-platform.
- BlokedPopupContainers are no longer ConstrainedWindows.
- There is now a cross platform base class that contains most of the model/controller logic. The view now inherits from it. This is an improvement.
Review URL: http://codereview.chromium.org/119006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17483 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/blocked_popup_container.cc')
-rw-r--r-- | chrome/browser/views/blocked_popup_container.cc | 433 |
1 files changed, 68 insertions, 365 deletions
diff --git a/chrome/browser/views/blocked_popup_container.cc b/chrome/browser/views/blocked_popup_container.cc index fba9780..38fa3a5 100644 --- a/chrome/browser/views/blocked_popup_container.cc +++ b/chrome/browser/views/blocked_popup_container.cc @@ -11,6 +11,7 @@ #include "chrome/browser/views/blocked_popup_container.h" #include <math.h> +#include <windows.h> #include "app/gfx/canvas.h" #include "app/gfx/path.h" @@ -21,19 +22,14 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "views/background.h" #include "views/controls/button/image_button.h" -namespace { -// A number larger than the internal popup count on the Renderer; meant for -// preventing a compromised renderer from exhausting GDI memory by spawning -// infinite windows. -const int kImpossibleNumberOfPopups = 30; +#include "views/controls/scrollbar/native_scroll_bar.h" +namespace { // The minimal border around the edge of the notification. const int kSmallPadding = 2; @@ -78,10 +74,10 @@ const SkScalar kRoundedCornerRad[8] = { 0 }; -} +} // namespace BlockedPopupContainerView::BlockedPopupContainerView( - BlockedPopupContainer* container) + BlockedPopupContainerImpl* container) : container_(container) { ResourceBundle &resource_bundle = ResourceBundle::GetSharedInstance(); @@ -200,7 +196,8 @@ void BlockedPopupContainerView::ButtonPressed(views::Button* sender) { if (!hosts.empty() && (popup_count > 0)) launch_menu_->AppendSeparator(); for (size_t i = 0; i < hosts.size(); ++i) { - launch_menu_->AppendMenuItem(kImpossibleNumberOfPopups + i + 1, + launch_menu_->AppendMenuItem( + BlockedPopupContainer::kImpossibleNumberOfPopups + i + 1, l10n_util::GetStringF(IDS_POPUP_HOST_FORMAT, hosts[i]), views::Menu::NORMAL); } @@ -215,9 +212,9 @@ void BlockedPopupContainerView::ButtonPressed(views::Button* sender) { } bool BlockedPopupContainerView::IsItemChecked(int id) const { - if (id > kImpossibleNumberOfPopups) { + if (id > BlockedPopupContainer::kImpossibleNumberOfPopups) { return container_->IsHostWhitelisted(static_cast<size_t>( - id - kImpossibleNumberOfPopups - 1)); + id - BlockedPopupContainer::kImpossibleNumberOfPopups - 1)); } return false; @@ -226,114 +223,29 @@ bool BlockedPopupContainerView::IsItemChecked(int id) const { void BlockedPopupContainerView::ExecuteCommand(int id) { DCHECK_GT(id, 0); size_t id_size_t = static_cast<size_t>(id); - if (id_size_t > kImpossibleNumberOfPopups) { + if (id_size_t > BlockedPopupContainer::kImpossibleNumberOfPopups) { // Decrement id since all index based commands have 1 added to them. (See // ButtonPressed() for detail). container_->ToggleWhitelistingForHost( - id_size_t - kImpossibleNumberOfPopups - 1); + id_size_t - BlockedPopupContainer::kImpossibleNumberOfPopups - 1); } else { container_->LaunchPopupAtIndex(id_size_t - 1); } } -BlockedPopupContainer::~BlockedPopupContainer() { -} - -// static -void BlockedPopupContainer::RegisterUserPrefs(PrefService* prefs) { - prefs->RegisterListPref(prefs::kPopupWhitelistedHosts); +BlockedPopupContainerImpl::~BlockedPopupContainerImpl() { } // static BlockedPopupContainer* BlockedPopupContainer::Create( TabContents* owner, Profile* profile, const gfx::Point& initial_anchor) { - BlockedPopupContainer* container = - new BlockedPopupContainer(owner, profile->GetPrefs()); + BlockedPopupContainerImpl* container = + new BlockedPopupContainerImpl(owner, profile->GetPrefs()); container->Init(initial_anchor); return container; } -void BlockedPopupContainer::AddTabContents(TabContents* tab_contents, - const gfx::Rect& bounds, - const std::string& host) { - // Show whitelisted popups immediately. - bool whitelisted = !!whitelist_.count(host); - if (whitelisted) - owner_->AddNewContents(tab_contents, NEW_POPUP, bounds, true, GURL()); - - if (has_been_dismissed_) { - // Don't want to show any other UI. - if (!whitelisted) - delete tab_contents; // Discard blocked popups entirely. - return; - } - - if (whitelisted) { - // Listen for this popup's destruction, so if the user closes it manually, - // we'll know to stop caring about it. - registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(tab_contents)); - - unblocked_popups_[tab_contents] = host; - } else { - if (blocked_popups_.size() >= kImpossibleNumberOfPopups) { - delete tab_contents; - LOG(INFO) << "Warning: Renderer is sending more popups to us than should " - "be possible. Renderer compromised?"; - return; - } - blocked_popups_.push_back(BlockedPopup(tab_contents, bounds, host)); - - tab_contents->set_delegate(this); - } - - PopupHosts::const_iterator i(popup_hosts_.find(host)); - if (i == popup_hosts_.end()) - popup_hosts_[host] = whitelisted; - else - DCHECK_EQ(whitelisted, i->second); - - // Update UI. - container_view_->UpdateLabel(); - SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); - if (!Animation::IsAnimating() && visibility_percentage_ < 1.0) { - in_show_animation_ = true; - Animation::SetDuration(kShowAnimationDurationMS); - Animation::Start(); - } - owner_->PopupNotificationVisibilityChanged(true); -} - -void BlockedPopupContainer::LaunchPopupAtIndex(size_t index) { - if (index >= blocked_popups_.size()) - return; - - // Open the popup. - BlockedPopups::iterator i(blocked_popups_.begin() + index); - TabContents* tab_contents = i->tab_contents; - tab_contents->set_delegate(NULL); - owner_->AddNewContents(tab_contents, NEW_POPUP, i->bounds, true, GURL()); - - const std::string& host = i->host; - if (!host.empty()) { - // Listen for this popup's destruction, so if the user closes it manually, - // we'll know to stop caring about it. - registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(tab_contents)); - - // Add the popup to the unblocked list. (Do this before the below call!) - unblocked_popups_[tab_contents] = i->host; - } - - // Remove the popup from the blocked list. - EraseDataForPopupAndUpdateUI(i); -} - -size_t BlockedPopupContainer::GetBlockedPopupCount() const { - return blocked_popups_.size(); -} - -void BlockedPopupContainer::GetURLAndTitleForPopup(size_t index, +void BlockedPopupContainerImpl::GetURLAndTitleForPopup(size_t index, std::wstring* url, std::wstring* title) const { DCHECK(url); @@ -344,7 +256,7 @@ void BlockedPopupContainer::GetURLAndTitleForPopup(size_t index, *title = UTF16ToWideHack(tab_contents->GetTitle()); } -std::vector<std::wstring> BlockedPopupContainer::GetHosts() const { +std::vector<std::wstring> BlockedPopupContainerImpl::GetHosts() const { std::vector<std::wstring> hosts; for (PopupHosts::const_iterator i(popup_hosts_.begin()); i != popup_hosts_.end(); ++i) @@ -352,187 +264,61 @@ std::vector<std::wstring> BlockedPopupContainer::GetHosts() const { return hosts; } -bool BlockedPopupContainer::IsHostWhitelisted(size_t index) const { - PopupHosts::const_iterator i(ConvertHostIndexToIterator(index)); - return (i == popup_hosts_.end()) ? false : i->second; -} - -void BlockedPopupContainer::ToggleWhitelistingForHost(size_t index) { - PopupHosts::const_iterator i(ConvertHostIndexToIterator(index)); - const std::string& host = i->first; - bool should_whitelist = !i->second; - popup_hosts_[host] = should_whitelist; - - ListValue* whitelist_pref = - prefs_->GetMutableList(prefs::kPopupWhitelistedHosts); - if (should_whitelist) { - whitelist_.insert(host); - whitelist_pref->Append(new StringValue(host)); - - // Open the popups in order. - for (size_t j = 0; j < blocked_popups_.size(); ) { - if (blocked_popups_[j].host == host) - LaunchPopupAtIndex(j); // This shifts the rest of the entries down. - else - ++j; - } - } else { - // Remove from whitelist. - whitelist_.erase(host); - whitelist_pref->Remove(StringValue(host)); - - for (UnblockedPopups::iterator i(unblocked_popups_.begin()); - i != unblocked_popups_.end(); ) { - TabContents* tab_contents = i->first; - TabContentsDelegate* delegate = tab_contents->delegate(); - if ((i->second == host) && delegate->IsPopup(tab_contents)) { - // Convert the popup back into a blocked popup. - delegate->DetachContents(tab_contents); - tab_contents->set_delegate(this); - - // Add the popup to the blocked list. (Do this before the below call!) - gfx::Rect bounds; - tab_contents->GetContainerBounds(&bounds); - blocked_popups_.push_back(BlockedPopup(tab_contents, bounds, host)); - - // Remove the popup from the unblocked list. - i = EraseDataForPopupAndUpdateUI(i); - } else { - ++i; - } - } - } -} - -void BlockedPopupContainer::CloseAll() { - ClearData(); - HideSelf(); -} - // Overridden from ConstrainedWindow: -void BlockedPopupContainer::CloseConstrainedWindow() { +void BlockedPopupContainerImpl::Destroy() { ClearData(); - - // Broadcast to all observers of NOTIFY_CWINDOW_CLOSED. - // One example of such an observer is AutomationCWindowTracker in the - // automation component. - NotificationService::current()->Notify(NotificationType::CWINDOW_CLOSED, - Source<ConstrainedWindow>(this), - NotificationService::NoDetails()); - Close(); } -void BlockedPopupContainer::RepositionConstrainedWindowTo( - const gfx::Point& anchor_point) { - anchor_point_ = anchor_point; - SetPosition(); -} +void BlockedPopupContainerImpl::RepositionBlockedPopupContainer( + gfx::NativeView view) { + if (::IsWindow(view)) { + CRect client_rect; + ::GetClientRect(view, &client_rect); -// Overridden from TabContentsDelegate: -void BlockedPopupContainer::OpenURLFromTab(TabContents* source, - const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - owner_->OpenURL(url, referrer, disposition, transition); -} + // TODO(erg): There's no way to detect whether scroll bars are + // visible, so for beta, we're just going to assume that the + // vertical scroll bar is visible, and not care about covering up + // the horizontal scroll bar. Fixing this is half of + // http://b/1118139. + gfx::Point anchor_position( + client_rect.Width() - + views::NativeScrollBar::GetVerticalScrollBarWidth(), + client_rect.Height()); -void BlockedPopupContainer::AddNewContents(TabContents* source, - TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_position, - bool user_gesture) { - owner_->AddNewContents(new_contents, disposition, initial_position, - user_gesture, GURL()); -} - -void BlockedPopupContainer::CloseContents(TabContents* source) { - for (BlockedPopups::iterator it = blocked_popups_.begin(); - it != blocked_popups_.end(); ++it) { - TabContents* tab_contents = it->tab_contents; - if (tab_contents == source) { - tab_contents->set_delegate(NULL); - EraseDataForPopupAndUpdateUI(it); - delete tab_contents; - break; - } - } -} - -void BlockedPopupContainer::MoveContents(TabContents* source, - const gfx::Rect& new_bounds) { - for (BlockedPopups::iterator it = blocked_popups_.begin(); - it != blocked_popups_.end(); ++it) { - if (it->tab_contents == source) { - it->bounds = new_bounds; - break; - } + RepositionWindowTo(anchor_position); } } -bool BlockedPopupContainer::IsPopup(TabContents* source) { - return true; -} - -TabContents* BlockedPopupContainer::GetConstrainingContents( - TabContents* source) { - return owner_; -} - -ExtensionFunctionDispatcher* BlockedPopupContainer:: - CreateExtensionFunctionDispatcher(RenderViewHost* render_view_host, - const std::string& extension_id) { - return new ExtensionFunctionDispatcher(render_view_host, NULL, extension_id); -} - // private: -BlockedPopupContainer::BlockedPopupContainer(TabContents* owner, - PrefService* prefs) - : Animation(kFramerate, NULL), - owner_(owner), - prefs_(prefs), +BlockedPopupContainerImpl::BlockedPopupContainerImpl(TabContents* owner, + PrefService* prefs) + : BlockedPopupContainer(owner, prefs), + Animation(kFramerate, NULL), container_view_(NULL), - has_been_dismissed_(false), in_show_animation_(false), visibility_percentage_(0) { - // Copy whitelist pref into local member that's easier to use. - const ListValue* whitelist_pref = - prefs_->GetList(prefs::kPopupWhitelistedHosts); - // Careful: The returned value could be NULL if the pref has never been set. - if (whitelist_pref != NULL) { - for (ListValue::const_iterator i(whitelist_pref->begin()); - i != whitelist_pref->end(); ++i) { - std::string host; - (*i)->GetAsString(&host); - whitelist_.insert(host); - } - } } -void BlockedPopupContainer::AnimateToState(double state) { - visibility_percentage_ = in_show_animation_ ? state : (1 - state); +void BlockedPopupContainerImpl::RepositionWindowTo( + const gfx::Point& anchor_point) { + anchor_point_ = anchor_point; SetPosition(); } -void BlockedPopupContainer::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); - TabContents* tab_contents = Source<TabContents>(source).ptr(); - UnblockedPopups::iterator i(unblocked_popups_.find(tab_contents)); - DCHECK(i != unblocked_popups_.end()); - EraseDataForPopupAndUpdateUI(i); +void BlockedPopupContainerImpl::AnimateToState(double state) { + visibility_percentage_ = in_show_animation_ ? state : (1 - state); + SetPosition(); } -void BlockedPopupContainer::OnFinalMessage(HWND window) { - owner_->WillClose(this); +void BlockedPopupContainerImpl::OnFinalMessage(HWND window) { + GetConstrainingContents(NULL)->WillCloseBlockedPopupContainer(this); ClearData(); WidgetWin::OnFinalMessage(window); } -void BlockedPopupContainer::OnSize(UINT param, const CSize& size) { +void BlockedPopupContainerImpl::OnSize(UINT param, const CSize& size) { // Set the window region so we have rounded corners on the top. SkRect rect; rect.set(0, 0, SkIntToScalar(size.cx), SkIntToScalar(size.cy)); @@ -543,24 +329,41 @@ void BlockedPopupContainer::OnSize(UINT param, const CSize& size) { ChangeSize(param, size); } -void BlockedPopupContainer::Init(const gfx::Point& initial_anchor) { +void BlockedPopupContainerImpl::Init(const gfx::Point& initial_anchor) { container_view_ = new BlockedPopupContainerView(this); container_view_->SetVisible(true); set_window_style(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); - WidgetWin::Init(owner_->GetNativeView(), gfx::Rect(), false); + WidgetWin::Init(GetConstrainingContents(NULL)->GetNativeView(), gfx::Rect(), + false); SetContentsView(container_view_); - RepositionConstrainedWindowTo(initial_anchor); + RepositionWindowTo(initial_anchor); } -void BlockedPopupContainer::HideSelf() { +void BlockedPopupContainerImpl::ShowSelf() { + SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + if (!Animation::IsAnimating() && visibility_percentage_ < 1.0) { + in_show_animation_ = true; + Animation::SetDuration(kShowAnimationDurationMS); + Animation::Start(); + } +} + +void BlockedPopupContainerImpl::HideSelf() { in_show_animation_ = false; Animation::SetDuration(kHideAnimationDurationMS); Animation::Start(); - owner_->PopupNotificationVisibilityChanged(false); + BlockedPopupContainer::HideSelf(); +} + +void BlockedPopupContainerImpl::UpdateLabel() { + if (blocked_popups_.empty() && unblocked_popups_.empty()) + HideSelf(); + else + container_view_->UpdateLabel(); } -void BlockedPopupContainer::SetPosition() { +void BlockedPopupContainerImpl::SetPosition() { gfx::Size size = container_view_->GetPreferredSize(); int base_x = anchor_point_.x() - size.width(); int base_y = anchor_point_.y() - size.height(); @@ -590,103 +393,3 @@ void BlockedPopupContainer::SetPosition() { SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); } } - -void BlockedPopupContainer::ClearData() { - for (BlockedPopups::iterator i(blocked_popups_.begin()); - i != blocked_popups_.end(); ++i) { - TabContents* tab_contents = i->tab_contents; - tab_contents->set_delegate(NULL); - delete tab_contents; - } - blocked_popups_.clear(); - - registrar_.RemoveAll(); - unblocked_popups_.clear(); - - popup_hosts_.clear(); -} - -BlockedPopupContainer::PopupHosts::const_iterator - BlockedPopupContainer::ConvertHostIndexToIterator(size_t index) const { - if (index >= popup_hosts_.size()) - return popup_hosts_.end(); - // If only there was a std::map::const_iterator::operator +=() ... - PopupHosts::const_iterator i(popup_hosts_.begin()); - for (size_t j = 0; j < index; ++j) - ++i; - return i; -} - -void BlockedPopupContainer::EraseDataForPopupAndUpdateUI( - BlockedPopups::iterator i) { - // Erase the host if this is the last popup for that host. - const std::string& host = i->host; - if (!host.empty()) { - bool should_erase_host = true; - for (BlockedPopups::const_iterator j(blocked_popups_.begin()); - j != blocked_popups_.end(); ++j) { - if ((j != i) && (j->host == host)) { - should_erase_host = false; - break; - } - } - if (should_erase_host) { - for (UnblockedPopups::const_iterator j(unblocked_popups_.begin()); - j != unblocked_popups_.end(); ++j) { - if (j->second == host) { - should_erase_host = false; - break; - } - } - if (should_erase_host) - popup_hosts_.erase(host); - } - } - - // Erase the popup and update the UI. - blocked_popups_.erase(i); - if (blocked_popups_.empty() && unblocked_popups_.empty()) - HideSelf(); - else - container_view_->UpdateLabel(); -} - -BlockedPopupContainer::UnblockedPopups::iterator - BlockedPopupContainer::EraseDataForPopupAndUpdateUI( - UnblockedPopups::iterator i) { - // Stop listening for this popup's destruction. - registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(i->first)); - - // Erase the host if this is the last popup for that host. - const std::string& host = i->second; - if (!host.empty()) { - bool should_erase_host = true; - for (UnblockedPopups::const_iterator j(unblocked_popups_.begin()); - j != unblocked_popups_.end(); ++j) { - if ((j != i) && (j->second == host)) { - should_erase_host = false; - break; - } - } - if (should_erase_host) { - for (BlockedPopups::const_iterator j(blocked_popups_.begin()); - j != blocked_popups_.end(); ++j) { - if (j->host == host) { - should_erase_host = false; - break; - } - } - if (should_erase_host) - popup_hosts_.erase(host); - } - } - - // Erase the popup and update the UI. - UnblockedPopups::iterator next_popup = unblocked_popups_.erase(i); - if (blocked_popups_.empty() && unblocked_popups_.empty()) - HideSelf(); - else - container_view_->UpdateLabel(); - return next_popup; -} |