summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc77
-rw-r--r--chrome/browser/tab_contents/tab_contents.h30
-rw-r--r--chrome/browser/views/blocked_popup_container.cc225
-rw-r--r--chrome/browser/views/blocked_popup_container.h68
-rw-r--r--chrome/common/render_messages_internal.h2
-rw-r--r--chrome/renderer/render_view.cc8
-rw-r--r--chrome/renderer/render_view.h4
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