diff options
-rw-r--r-- | chrome/app/generated_resources.grd | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 77 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 30 | ||||
-rw-r--r-- | chrome/browser/views/blocked_popup_container.cc | 225 | ||||
-rw-r--r-- | chrome/browser/views/blocked_popup_container.h | 68 | ||||
-rw-r--r-- | chrome/common/render_messages_internal.h | 2 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 4 |
9 files changed, 302 insertions, 117 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 6ff9aeb..683e65a 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3716,6 +3716,9 @@ each locale. --> <message name="IDS_POPUP_TITLE_FORMAT" desc="Order of URL - Title on the popup"> <ph name="URL">$1</ph> - <ph name="WINDOW_TITLE">$2</ph> </message> + <message name="IDS_POPUP_HOST_FORMAT" desc="Checkable menu item to always allow popups from a particular hostname"> + Always show pop-ups from <ph name="URL">$1</ph> + </message> <!-- Multiple download warning--> <message name="IDS_MULTI_DOWNLOAD_WARNING" desc="Warning invoked if multiple downloads are attempted without user interaction."> diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 8991f5f..b31181b 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -1092,7 +1092,7 @@ void RenderViewHost::DisassociateFromPopupCount() { } void RenderViewHost::PopupNotificationVisibilityChanged(bool visible) { - Send(new ViewMsg_PopupNotificationVisiblityChanged(routing_id(), visible)); + Send(new ViewMsg_PopupNotificationVisibilityChanged(routing_id(), visible)); } void RenderViewHost::OnMsgGoToEntryAtOffset(int offset) { diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 743e1bd..14cdd22 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -791,16 +791,25 @@ void TabContents::AddNewContents(TabContents* new_contents, return; #if defined(OS_WIN) + bool constrain_popup = false; if ((disposition == NEW_POPUP) && !user_gesture && !CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisablePopupBlocking)) { - // Unrequested popups from normal pages are constrained. - TabContents* popup_owner = this; + // Unrequested popups from normal pages are constrained unless they're in + // the whitelist. + std::string host; + if (creator_url.is_valid()) + host = creator_url.host(); + constrain_popup = true; // TODO(pkasting): Add whitelist + TabContents* our_owner = delegate_->GetConstrainingContents(this); - if (our_owner) - popup_owner = our_owner; - popup_owner->AddConstrainedPopup(new_contents, initial_pos); - } else { + TabContents* popup_owner = our_owner ? our_owner : this; + if (constrain_popup) + popup_owner->AddConstrainedPopup(new_contents, initial_pos, host); + else + popup_owner->OnPopupOpenedFromWhitelistedHost(host); + } + if (!constrain_popup) { new_contents->DisassociateFromPopupCount(); delegate_->AddNewContents(this, new_contents, disposition, initial_pos, @@ -816,28 +825,9 @@ void TabContents::AddNewContents(TabContents* new_contents, } #if defined(OS_WIN) -void TabContents::AddConstrainedPopup(TabContents* new_contents, - const gfx::Rect& initial_pos) { - if (!blocked_popups_) { - CRect client_rect; - GetClientRect(GetNativeView(), &client_rect); - gfx::Point anchor_position( - client_rect.Width() - - views::NativeScrollBar::GetVerticalScrollBarWidth(), - client_rect.Height()); - - blocked_popups_ = BlockedPopupContainer::Create( - this, profile(), anchor_position); - child_windows_.push_back(blocked_popups_); - } - - blocked_popups_->AddTabContents(new_contents, initial_pos); - PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); -} - void TabContents::CloseAllSuppressedPopups() { if (blocked_popups_) - blocked_popups_->CloseAllPopups(); + blocked_popups_->CloseAll(); } #endif @@ -1142,6 +1132,12 @@ bool TabContents::IsActiveEntry(int32 page_id) { active_entry->page_id() == page_id); } +#if defined(OS_WIN) +void TabContents::SetWhitelistForHost(const std::string& host, bool whitelist) { + // TODO(pkasting): Add whitelist +} +#endif + // Notifies the RenderWidgetHost instance about the fact that the page is // loading, or done loading and calls the base implementation. void TabContents::SetIsLoading(bool is_loading, @@ -1174,6 +1170,33 @@ void TabContents::SetIsLoading(bool is_loading, } #if defined(OS_WIN) +void TabContents::CreateBlockedPopupContainerIfNecessary() { + if (blocked_popups_) + return; + + CRect client_rect; + GetClientRect(GetNativeView(), &client_rect); + gfx::Point anchor_position( + client_rect.Width() - views::NativeScrollBar::GetVerticalScrollBarWidth(), + client_rect.Height()); + blocked_popups_ = BlockedPopupContainer::Create(this, profile(), + anchor_position); + child_windows_.push_back(blocked_popups_); +} + +void TabContents::AddConstrainedPopup(TabContents* new_contents, + const gfx::Rect& initial_pos, + const std::string& host) { + CreateBlockedPopupContainerIfNecessary(); + blocked_popups_->AddTabContents(new_contents, initial_pos, host); + PopupNotificationVisibilityChanged(ShowingBlockedPopupNotification()); +} + +void TabContents::OnPopupOpenedFromWhitelistedHost(const std::string& host) { + CreateBlockedPopupContainerIfNecessary(); + blocked_popups_->OnPopupOpenedFromWhitelistedHost(host); +} + // TODO(brettw) This should be on the TabContentsView. void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { // TODO(erg): There's no way to detect whether scroll bars are @@ -1192,7 +1215,7 @@ void TabContents::RepositionSupressedPopupsToFit(const gfx::Size& new_size) { bool TabContents::ShowingBlockedPopupNotification() const { return blocked_popups_ != NULL && - blocked_popups_->GetTabContentsCount() != 0; + blocked_popups_->GetBlockedPopupCount() != 0; } #endif // defined(OS_WIN) diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 59549c4..ed063e2 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -341,11 +341,6 @@ class TabContents : public PageNavigator, bool user_gesture, const GURL& creator_url); - // Builds a ConstrainedWindow* for the incoming |new_contents| and - // adds it to child_windows_. - void AddConstrainedPopup(TabContents* new_contents, - const gfx::Rect& initial_pos); - // Closes all constrained windows that represent web popups that have not yet // been activated by the user and are as such auto-positioned in the bottom // right of the screen. This is a quick way for users to "clean up" a flurry @@ -570,6 +565,9 @@ class TabContents : public PageNavigator, render_view_host()->WindowMoveOrResizeStarted(); } + // Sets popup whitelisting state for |host| to |whitelist|. + void SetWhitelistForHost(const std::string& host, bool whitelist); + private: friend class NavigationController; // Used to access the child_windows_ (ConstrainedWindowList) for testing @@ -619,11 +617,28 @@ class TabContents : public PageNavigator, void SetIsLoading(bool is_loading, LoadNotificationDetails* details); + // Constructs |blocked_popups_| if need be. + void CreateBlockedPopupContainerIfNecessary(); + + // Adds the incoming |new_contents| to the |blocked_popups_| container. + void AddConstrainedPopup(TabContents* new_contents, + const gfx::Rect& initial_pos, + const std::string& host); + + // Notifies the |blocked_popups_| container that a popup has been opened from + // a particular whitelisted host. + void OnPopupOpenedFromWhitelistedHost(const std::string& host); + // Called by a derived class when the TabContents is resized, causing // suppressed constrained web popups to be repositioned to the new bounds // if necessary. void RepositionSupressedPopupsToFit(const gfx::Size& new_size); + // Whether we have a notification AND the notification owns popups windows. + // (We keep the notification object around even when it's not shown since it + // determines whether to show itself). + bool ShowingBlockedPopupNotification() const; + // Releases the download shelf. This method is used by MigrateShelfFrom. void ReleaseDownloadShelf(); @@ -635,11 +650,6 @@ class TabContents : public PageNavigator, typedef std::vector<ConstrainedWindow*> ConstrainedWindowList; ConstrainedWindowList child_windows_; - // Whether we have a notification AND the notification owns popups windows. - // (We keep the notification object around even when it's not shown since it - // determines whether to show itself). - bool ShowingBlockedPopupNotification() const; - // Expires InfoBars that need to be expired, according to the state carried // in |details|, in response to a new NavigationEntry being committed (the // user navigated to another page). diff --git a/chrome/browser/views/blocked_popup_container.cc b/chrome/browser/views/blocked_popup_container.cc index c6db1c6..82b9590 100644 --- a/chrome/browser/views/blocked_popup_container.cc +++ b/chrome/browser/views/blocked_popup_container.cc @@ -179,12 +179,26 @@ void BlockedPopupContainerView::ButtonPressed(views::Button* sender) { launch_menu_.reset(new Menu(this, Menu::TOPLEFT, container_->GetNativeView())); - int item_count = container_->GetTabContentsCount(); - for (int i = 0; i < item_count; ++i) { - std::wstring label = container_->GetDisplayStringForItem(i); + // Set items 1 .. popup_count as individual popups. + int popup_count = container_->GetBlockedPopupCount(); + for (int i = 0; i < popup_count; ++i) { + std::wstring url, title; + container_->GetURLAndTitleForPopup(i, &url, &title); // We can't just use the index into container_ here because Menu reserves // the value 0 as the nop command. - launch_menu_->AppendMenuItem(i + 1, label, Menu::NORMAL); + launch_menu_->AppendMenuItem(i + 1, + l10n_util::GetStringF(IDS_POPUP_TITLE_FORMAT, url, title), + Menu::NORMAL); + } + + // Set items (kImpossibleNumberOfPopups + 1) .. + // (kImpossibleNumberOfPopups + 1 + hosts.size()) as hosts. + std::vector<std::wstring> hosts(container_->GetHosts()); + if (!hosts.empty() && (popup_count > 0)) + launch_menu_->AppendSeparator(); + for (size_t i = 0; i < hosts.size(); ++i) { + launch_menu_->AppendMenuItem(kImpossibleNumberOfPopups + i + 1, + l10n_util::GetStringF(IDS_POPUP_HOST_FORMAT, hosts[i]), Menu::NORMAL); } launch_menu_->AppendSeparator(); @@ -198,7 +212,7 @@ void BlockedPopupContainerView::ButtonPressed(views::Button* sender) { launch_menu_->RunMenuAt(cursor_position.x, cursor_position.y); } else if (sender == close_button_) { container_->set_dismissed(); - container_->CloseAllPopups(); + container_->CloseAll(); } } @@ -206,15 +220,20 @@ bool BlockedPopupContainerView::IsItemChecked(int id) const { if (id == kNotifyMenuItem) return container_->GetShowBlockedPopupNotification(); + if (id > kImpossibleNumberOfPopups) + return container_->IsHostWhitelisted(id - kImpossibleNumberOfPopups - 1); + return false; } void BlockedPopupContainerView::ExecuteCommand(int id) { if (id == kNotifyMenuItem) { container_->ToggleBlockedPopupNotification(); - } else { + } else if (id > kImpossibleNumberOfPopups) { // Decrement id since all index based commands have 1 added to them. (See // ButtonPressed() for detail). + container_->ToggleWhitelistingForHost(id - kImpossibleNumberOfPopups - 1); + } else { container_->LaunchPopupIndex(id - 1); } } @@ -252,70 +271,127 @@ bool BlockedPopupContainer::GetShowBlockedPopupNotification() { } void BlockedPopupContainer::AddTabContents(TabContents* blocked_contents, - const gfx::Rect& bounds) { + const gfx::Rect& bounds, + const std::string& host) { if (has_been_dismissed_) { // We simply bounce this popup without notice. delete blocked_contents; return; } - if (blocked_popups_.size() > kImpossibleNumberOfPopups) { + if (blocked_popups_.size() >= kImpossibleNumberOfPopups) { delete blocked_contents; - LOG(INFO) << "Warning: Renderer is sending more popups to us then should be" + LOG(INFO) << "Warning: Renderer is sending more popups to us than should be" " possible. Renderer compromised?"; return; } blocked_contents->set_delegate(this); - blocked_popups_.push_back(std::make_pair(blocked_contents, bounds)); - container_view_->UpdatePopupCountLabel(); + blocked_popups_.push_back(BlockedPopup(blocked_contents, bounds, host)); + + PopupHosts::iterator i(popup_hosts_.find(host)); + if (i == popup_hosts_.end()) + popup_hosts_[host] = false; + else + DCHECK(!i->second); // This host was already reported as whitelisted! + container_view_->UpdatePopupCountLabel(); ShowSelf(); } -void BlockedPopupContainer::LaunchPopupIndex(int index) { - if (static_cast<size_t>(index) < blocked_popups_.size()) { - TabContents* contents = blocked_popups_[index].first; - gfx::Rect bounds = blocked_popups_[index].second; - blocked_popups_.erase(blocked_popups_.begin() + index); - container_view_->UpdatePopupCountLabel(); - - contents->set_delegate(NULL); - contents->DisassociateFromPopupCount(); - - // Pass this TabContents back to our owner, forcing the window to be - // displayed since user_gesture is true. - owner_->AddNewContents(contents, NEW_POPUP, bounds, true, GURL()); +void BlockedPopupContainer::OnPopupOpenedFromWhitelistedHost( + const std::string& host) { + if (has_been_dismissed_) + return; + + PopupHosts::const_iterator i(popup_hosts_.find(host)); + if (i == popup_hosts_.end()) { + popup_hosts_[host] = true; + ShowSelf(); + } else { + DCHECK(i->second); // This host was already reported as not whitelisted! } +} + +void BlockedPopupContainer::LaunchPopupIndex(int index) { + if (static_cast<size_t>(index) >= blocked_popups_.size()) + return; + + BlockedPopups::iterator i(blocked_popups_.begin() + index); + TabContents* contents = i->tab_contents; + gfx::Rect bounds(i->bounds); + EraseHostIfNeeded(i); + blocked_popups_.erase(i); + + contents->set_delegate(NULL); + contents->DisassociateFromPopupCount(); + + // Pass this TabContents back to our owner, forcing the window to be + // displayed since user_gesture is true. + owner_->AddNewContents(contents, NEW_POPUP, bounds, true, GURL()); - if (blocked_popups_.size() == 0) - CloseAllPopups(); + container_view_->UpdatePopupCountLabel(); + if (blocked_popups_.empty() && popup_hosts_.empty()) + HideSelf(); } -int BlockedPopupContainer::GetTabContentsCount() const { +int BlockedPopupContainer::GetBlockedPopupCount() const { return blocked_popups_.size(); } -std::wstring BlockedPopupContainer::GetDisplayStringForItem(int index) { - const GURL& url = blocked_popups_[index].first->GetURL().GetOrigin(); +void BlockedPopupContainer::GetURLAndTitleForPopup(int index, + std::wstring* url, + std::wstring* title) const { + DCHECK(url); + DCHECK(title); + TabContents* tab_contents = blocked_popups_[index].tab_contents; + const GURL& tab_contents_url = tab_contents->GetURL().GetOrigin(); + *url = UTF8ToWide(tab_contents_url.possibly_invalid_spec()); + *title = UTF16ToWideHack(tab_contents->GetTitle()); +} - std::wstring label = l10n_util::GetStringF( - IDS_POPUP_TITLE_FORMAT, - UTF8ToWide(url.possibly_invalid_spec()), - UTF16ToWideHack(blocked_popups_[index].first->GetTitle())); - return label; +std::vector<std::wstring> BlockedPopupContainer::GetHosts() const { + std::vector<std::wstring> hosts; + for (PopupHosts::const_iterator i(popup_hosts_.begin()); + i != popup_hosts_.end(); ++i) + hosts.push_back(UTF8ToWide(i->first)); + return hosts; } -void BlockedPopupContainer::CloseAllPopups() { - CloseEachTabContents(); - owner_->PopupNotificationVisibilityChanged(false); - container_view_->UpdatePopupCountLabel(); +bool BlockedPopupContainer::IsHostWhitelisted(int index) const { + PopupHosts::const_iterator i(ConvertHostIndexToIterator(index)); + return (i == popup_hosts_.end()) ? false : i->second; +} + +void BlockedPopupContainer::ToggleWhitelistingForHost(int index) { + PopupHosts::const_iterator i(ConvertHostIndexToIterator(index)); + const std::string& host = i->first; + bool should_whitelist = !i->second; + owner_->SetWhitelistForHost(host, should_whitelist); + if (should_whitelist) { + for (int j = blocked_popups_.size() - 1; j >= 0; --j) { + if (blocked_popups_[j].host == host) + LaunchPopupIndex(j); + } + } else { + // TODO(pkasting): Should we have some kind of handle to the open popups, so + // we can hide them all here? + popup_hosts_.erase(host); // Can't use |i| because it's a const_iterator. + if (blocked_popups_.empty() && popup_hosts_.empty()) + HideSelf(); + } + // At this point i is invalid, since the item it points to was deleted (on + // both conditional arms). +} + +void BlockedPopupContainer::CloseAll() { + ClearData(); HideSelf(); } // Overridden from ConstrainedWindow: void BlockedPopupContainer::CloseConstrainedWindow() { - CloseEachTabContents(); + ClearData(); // Broadcast to all observers of NOTIFY_CWINDOW_CLOSED. // One example of such an observer is AutomationCWindowTracker in the @@ -335,7 +411,7 @@ void BlockedPopupContainer::RepositionConstrainedWindowTo( std::wstring BlockedPopupContainer::GetWindowTitle() const { return l10n_util::GetStringF(IDS_POPUPS_BLOCKED_COUNT, - IntToWString(GetTabContentsCount())); + IntToWString(GetBlockedPopupCount())); } const gfx::Rect& BlockedPopupContainer::GetCurrentBounds() const { @@ -361,25 +437,27 @@ void BlockedPopupContainer::AddNewContents(TabContents* source, } void BlockedPopupContainer::CloseContents(TabContents* source) { - for (std::vector<std::pair<TabContents*, gfx::Rect> >::iterator it = - blocked_popups_.begin(); it != blocked_popups_.end(); ++it) { - if (it->first == source) { - it->first->set_delegate(NULL); + for (BlockedPopups::iterator it = blocked_popups_.begin(); + it != blocked_popups_.end(); ++it) { + if (it->tab_contents == source) { + it->tab_contents->set_delegate(NULL); + EraseHostIfNeeded(it); blocked_popups_.erase(it); + container_view_->UpdatePopupCountLabel(); break; } } - if (blocked_popups_.size() == 0) - CloseAllPopups(); + if (blocked_popups_.empty()) + HideSelf(); } void BlockedPopupContainer::MoveContents(TabContents* source, - const gfx::Rect& position) { - for (std::vector<std::pair<TabContents*, gfx::Rect> >::iterator it = - blocked_popups_.begin(); it != blocked_popups_.end(); ++it) { - if (it->first == source) { - it->second = position; + 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; } } @@ -402,18 +480,14 @@ ExtensionFunctionDispatcher* BlockedPopupContainer:: // Overridden from Animation: void BlockedPopupContainer::AnimateToState(double state) { - if (in_show_animation_) - visibility_percentage_ = state; - else - visibility_percentage_ = 1 - state; - + visibility_percentage_ = in_show_animation_ ? state : (1 - state); SetPosition(); } // Override from views::WidgetWin: void BlockedPopupContainer::OnFinalMessage(HWND window) { owner_->WillClose(this); - CloseEachTabContents(); + ClearData(); WidgetWin::OnFinalMessage(window); } @@ -449,6 +523,7 @@ void BlockedPopupContainer::HideSelf() { in_show_animation_ = false; Animation::SetDuration(kHideAnimationDurationMS); Animation::Start(); + owner_->PopupNotificationVisibilityChanged(false); } void BlockedPopupContainer::ShowSelf() { @@ -458,6 +533,7 @@ void BlockedPopupContainer::ShowSelf() { Animation::SetDuration(kShowAnimationDurationMS); Animation::Start(); } + owner_->PopupNotificationVisibilityChanged(true); } void BlockedPopupContainer::SetPosition() { @@ -481,12 +557,37 @@ void BlockedPopupContainer::SetPosition() { } } -void BlockedPopupContainer::CloseEachTabContents() { - while (!blocked_popups_.empty()) { - blocked_popups_.back().first->set_delegate(NULL); - delete blocked_popups_.back().first; - blocked_popups_.pop_back(); +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(); + popup_hosts_.clear(); +} + +BlockedPopupContainer::PopupHosts::const_iterator + BlockedPopupContainer::ConvertHostIndexToIterator(int index) const { + if (static_cast<size_t>(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 (int j = 0; j < index; ++j) + ++i; + return i; +} + +void BlockedPopupContainer::EraseHostIfNeeded(BlockedPopups::iterator i) { + const std::string& host = i->host; + if (host.empty()) + return; + for (BlockedPopups::const_iterator j(blocked_popups_.begin()); + j != blocked_popups_.end(); ++j) { + if ((j != i) && (j->host == host)) + return; + } + popup_hosts_.erase(host); } diff --git a/chrome/browser/views/blocked_popup_container.h b/chrome/browser/views/blocked_popup_container.h index 214b8f8..80112e5 100644 --- a/chrome/browser/views/blocked_popup_container.h +++ b/chrome/browser/views/blocked_popup_container.h @@ -104,19 +104,39 @@ class BlockedPopupContainer : public ConstrainedWindow, // Adds a Tabbed contents to this container. |bounds| are the window bounds // requested by the popup window. - void AddTabContents(TabContents* blocked_contents, const gfx::Rect& bounds); + void AddTabContents(TabContents* blocked_contents, + const gfx::Rect& bounds, + const std::string& host); + + // Called when a popup from whitelisted host |host| is opened, so we can show + // the "stop whitelisting" UI. + void OnPopupOpenedFromWhitelistedHost(const std::string& host); // Creates a window from blocked popup |index|. void LaunchPopupIndex(int index); // Returns the number of blocked popups - int GetTabContentsCount() const; + int GetBlockedPopupCount() const; + + // Returns the URL and title for popup |index|, used to construct a string for + // display. + void GetURLAndTitleForPopup(int index, + std::wstring* url, + std::wstring* title) const; + + // Returns the names of hosts showing popups. + std::vector<std::wstring> GetHosts() const; + + // Returns true if host |index| is whitelisted. Returns false if |index| is + // invalid. + bool IsHostWhitelisted(int index) const; - // Returns the string to display to the user in the menu for item |index|. - std::wstring GetDisplayStringForItem(int index); + // If host |index| is currently whitelisted, un-whitelists it. Otherwise, + // whitelists it and opens all blocked popups from it. + void ToggleWhitelistingForHost(int index); // Deletes all popups and hides the interface parts. - void CloseAllPopups(); + void CloseAll(); // Called to force this container to never show itself again. void set_dismissed() { has_been_dismissed_ = true; } @@ -168,7 +188,7 @@ class BlockedPopupContainer : public ConstrainedWindow, virtual void CloseContents(TabContents* source); // Changes the opening rectangle associated with |source|. - virtual void MoveContents(TabContents* source, const gfx::Rect& pos); + virtual void MoveContents(TabContents* source, const gfx::Rect& new_bounds); // Always returns true. virtual bool IsPopup(TabContents* source); @@ -207,6 +227,22 @@ class BlockedPopupContainer : public ConstrainedWindow, virtual void OnSize(UINT param, const CSize& size); private: + struct BlockedPopup { + BlockedPopup(TabContents* tab_contents, + const gfx::Rect& bounds, + const std::string& host) + : tab_contents(tab_contents), bounds(bounds), host(host) { + } + + TabContents* tab_contents; + gfx::Rect bounds; + std::string host; + }; + typedef std::vector<BlockedPopup> BlockedPopups; + + // string is hostname. bool is whitelisted status. + typedef std::map<std::string, bool> PopupHosts; + // Creates a container for a certain TabContents. BlockedPopupContainer(TabContents* owner, Profile* profile); @@ -225,14 +261,26 @@ class BlockedPopupContainer : public ConstrainedWindow, // change. void SetPosition(); - // Deletes each contents in |blocked_popups_|. - void CloseEachTabContents(); + // Deletes all local state. + void ClearData(); + + // Helper function to convert a host index (which the view uses) into an + // iterator into |popup_hosts_|. Returns popup_hosts_.end() if |index| is + // invalid. + PopupHosts::const_iterator ConvertHostIndexToIterator(int index) const; + + // If the popup at |i| is the last one associated with its host, removes the + // host from the host list. + void EraseHostIfNeeded(BlockedPopups::iterator i); // The TabContents that owns and constrains this BlockedPopupContainer. TabContents* owner_; - // The TabContents and initial positions of all blocked popups. - std::vector<std::pair<TabContents*, gfx::Rect> > blocked_popups_; + // Information about all blocked popups. + BlockedPopups blocked_popups_; + + // Information about all popup hosts. + PopupHosts popup_hosts_; // Our associated view object. BlockedPopupContainerView* container_view_; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index a74e54b..fe12745f 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -496,7 +496,7 @@ IPC_BEGIN_MESSAGES(View) // Sent by the Browser process to alert a window about whether a blocked // popup notification is visible. The renderer assumes every new window is a // blocked popup until notified otherwise. - IPC_MESSAGE_ROUTED1(ViewMsg_PopupNotificationVisiblityChanged, + IPC_MESSAGE_ROUTED1(ViewMsg_PopupNotificationVisibilityChanged, bool /* Whether it is visible */) // Sent by AudioRendererHost to renderer to request an audio packet. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index d173537..03df749 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -418,8 +418,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { OnDisassociateFromPopupCount) IPC_MESSAGE_HANDLER(ViewMsg_AutofillSuggestions, OnReceivedAutofillSuggestions) - IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisiblityChanged, - OnPopupNotificationVisiblityChanged) + IPC_MESSAGE_HANDLER(ViewMsg_PopupNotificationVisibilityChanged, + OnPopupNotificationVisibilityChanged) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse) IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode) @@ -1698,7 +1698,7 @@ void RenderView::OnReceivedAutofillSuggestions( default_suggestion_index); } -void RenderView::OnPopupNotificationVisiblityChanged(bool visible) { +void RenderView::OnPopupNotificationVisibilityChanged(bool visible) { popup_notification_visible_ = visible; } @@ -1956,7 +1956,7 @@ void RenderView::Show(WebWidget* webwidget, WindowOpenDisposition disposition) { } void RenderView::CloseWidgetSoon(WebWidget* webwidget) { - if (popup_notification_visible_ == false) + if (!popup_notification_visible_) RenderWidget::CloseWidgetSoon(webwidget); } diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index 8c34769..bdd415c 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -557,7 +557,7 @@ class RenderView : public RenderWidget, int default_suggestions_index); // Message that the popup notification has been shown or hidden. - void OnPopupNotificationVisiblityChanged(bool visible); + void OnPopupNotificationVisibilityChanged(bool visible); // Handles messages posted from automation. void OnMessageFromExternalHost(const std::string& message, @@ -765,7 +765,7 @@ class RenderView : public RenderWidget, // We need to prevent windows from closing themselves with a window.close() // call while a blocked popup notification is being displayed. We cannot - // synchronously querry the Browser process. We cannot wait for the Browser + // synchronously query the Browser process. We cannot wait for the Browser // process to send a message to us saying that a blocked popup notification // is being displayed. We instead assume that when we create a window off // this RenderView, that it is going to be blocked until we get a message |