// 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<TabContents*>* 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_;
}