// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/blocked_content_container.h" #include "content/browser/tab_contents/tab_contents.h" #include "ui/gfx/rect.h" // static const size_t BlockedContentContainer::kImpossibleNumberOfPopups = 30; struct BlockedContentContainer::BlockedContent { BlockedContent(TabContents* tab_contents, WindowOpenDisposition disposition, const gfx::Rect& bounds, bool user_gesture) : tab_contents(tab_contents), disposition(disposition), bounds(bounds), user_gesture(user_gesture) { } TabContents* tab_contents; WindowOpenDisposition disposition; gfx::Rect bounds; bool user_gesture; }; BlockedContentContainer::BlockedContentContainer(TabContents* owner) : owner_(owner) { } BlockedContentContainer::~BlockedContentContainer() {} void BlockedContentContainer::AddTabContents(TabContents* tab_contents, WindowOpenDisposition disposition, const gfx::Rect& bounds, bool user_gesture) { if (blocked_contents_.size() == (kImpossibleNumberOfPopups - 1)) { delete tab_contents; VLOG(1) << "Warning: Renderer is sending more popups to us than should be " "possible. Renderer compromised?"; return; } blocked_contents_.push_back( BlockedContent(tab_contents, disposition, bounds, user_gesture)); tab_contents->set_delegate(this); // Since the new tab_contents will not be showed, call WasHidden to change // its status on both RenderViewHost and RenderView. tab_contents->WasHidden(); if (blocked_contents_.size() == 1) owner_->PopupNotificationVisibilityChanged(true); } void BlockedContentContainer::LaunchForContents(TabContents* tab_contents) { // Open the popup. for (BlockedContents::iterator i(blocked_contents_.begin()); i != blocked_contents_.end(); ++i) { if (i->tab_contents == tab_contents) { // To support the owner blocking the content again we copy and erase // before attempting to add. BlockedContent content(*i); blocked_contents_.erase(i); i = blocked_contents_.end(); tab_contents->set_delegate(NULL); // We needn't call WasRestored to change its status because the // TabContents::AddNewContents will do it. owner_->AddOrBlockNewContents(tab_contents, content.disposition, content.bounds, content.user_gesture); break; } } if (blocked_contents_.empty()) Destroy(); } size_t BlockedContentContainer::GetBlockedContentsCount() const { return blocked_contents_.size(); } void BlockedContentContainer::GetBlockedContents( std::vector* blocked_contents) const { DCHECK(blocked_contents); for (BlockedContents::const_iterator i(blocked_contents_.begin()); i != blocked_contents_.end(); ++i) blocked_contents->push_back(i->tab_contents); } void BlockedContentContainer::Destroy() { for (BlockedContents::iterator i(blocked_contents_.begin()); i != blocked_contents_.end(); ++i) { TabContents* tab_contents = i->tab_contents; tab_contents->set_delegate(NULL); delete tab_contents; } blocked_contents_.clear(); owner_->WillCloseBlockedContentContainer(this); delete this; } // Overridden from TabContentsDelegate: void BlockedContentContainer::OpenURLFromTab(TabContents* source, const GURL& url, const GURL& referrer, WindowOpenDisposition disposition, PageTransition::Type transition) { owner_->OpenURL(url, referrer, disposition, transition); } void BlockedContentContainer::AddNewContents(TabContents* source, TabContents* new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_position, bool user_gesture) { owner_->AddOrBlockNewContents( new_contents, disposition, initial_position, user_gesture); } void BlockedContentContainer::CloseContents(TabContents* source) { for (BlockedContents::iterator i(blocked_contents_.begin()); i != blocked_contents_.end(); ++i) { TabContents* tab_contents = i->tab_contents; if (tab_contents == source) { tab_contents->set_delegate(NULL); blocked_contents_.erase(i); delete tab_contents; break; } } } void BlockedContentContainer::MoveContents(TabContents* source, const gfx::Rect& new_bounds) { for (BlockedContents::iterator i(blocked_contents_.begin()); i != blocked_contents_.end(); ++i) { if (i->tab_contents == source) { i->bounds = new_bounds; break; } } } bool BlockedContentContainer::IsPopup(const TabContents* source) const { // Assume everything added is a popup. This may turn out to be wrong, but // callers don't cache this information so it should be fine if the value ends // up changing. return true; } TabContents* BlockedContentContainer::GetConstrainingContents( TabContents* source) { return owner_; }