1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/blocked_content_container.h" 6 7#include "content/browser/tab_contents/tab_contents.h" 8#include "ui/gfx/rect.h" 9 10// static 11const size_t BlockedContentContainer::kImpossibleNumberOfPopups = 30; 12 13struct BlockedContentContainer::BlockedContent { 14 BlockedContent(TabContents* tab_contents, 15 WindowOpenDisposition disposition, 16 const gfx::Rect& bounds, 17 bool user_gesture) 18 : tab_contents(tab_contents), 19 disposition(disposition), 20 bounds(bounds), 21 user_gesture(user_gesture) { 22 } 23 24 TabContents* tab_contents; 25 WindowOpenDisposition disposition; 26 gfx::Rect bounds; 27 bool user_gesture; 28}; 29 30BlockedContentContainer::BlockedContentContainer(TabContents* owner) 31 : owner_(owner) { 32} 33 34BlockedContentContainer::~BlockedContentContainer() {} 35 36void BlockedContentContainer::AddTabContents(TabContents* tab_contents, 37 WindowOpenDisposition disposition, 38 const gfx::Rect& bounds, 39 bool user_gesture) { 40 if (blocked_contents_.size() == (kImpossibleNumberOfPopups - 1)) { 41 delete tab_contents; 42 VLOG(1) << "Warning: Renderer is sending more popups to us than should be " 43 "possible. Renderer compromised?"; 44 return; 45 } 46 47 blocked_contents_.push_back( 48 BlockedContent(tab_contents, disposition, bounds, user_gesture)); 49 tab_contents->set_delegate(this); 50 // Since the new tab_contents will not be showed, call WasHidden to change 51 // its status on both RenderViewHost and RenderView. 52 tab_contents->WasHidden(); 53 if (blocked_contents_.size() == 1) 54 owner_->PopupNotificationVisibilityChanged(true); 55} 56 57void BlockedContentContainer::LaunchForContents(TabContents* tab_contents) { 58 // Open the popup. 59 for (BlockedContents::iterator i(blocked_contents_.begin()); 60 i != blocked_contents_.end(); ++i) { 61 if (i->tab_contents == tab_contents) { 62 // To support the owner blocking the content again we copy and erase 63 // before attempting to add. 64 BlockedContent content(*i); 65 blocked_contents_.erase(i); 66 i = blocked_contents_.end(); 67 tab_contents->set_delegate(NULL); 68 // We needn't call WasRestored to change its status because the 69 // TabContents::AddNewContents will do it. 70 owner_->AddOrBlockNewContents(tab_contents, 71 content.disposition, 72 content.bounds, 73 content.user_gesture); 74 break; 75 } 76 } 77 78 if (blocked_contents_.empty()) 79 Destroy(); 80} 81 82size_t BlockedContentContainer::GetBlockedContentsCount() const { 83 return blocked_contents_.size(); 84} 85 86void BlockedContentContainer::GetBlockedContents( 87 std::vector<TabContents*>* blocked_contents) const { 88 DCHECK(blocked_contents); 89 for (BlockedContents::const_iterator i(blocked_contents_.begin()); 90 i != blocked_contents_.end(); ++i) 91 blocked_contents->push_back(i->tab_contents); 92} 93 94void BlockedContentContainer::Destroy() { 95 for (BlockedContents::iterator i(blocked_contents_.begin()); 96 i != blocked_contents_.end(); ++i) { 97 TabContents* tab_contents = i->tab_contents; 98 tab_contents->set_delegate(NULL); 99 delete tab_contents; 100 } 101 blocked_contents_.clear(); 102 owner_->WillCloseBlockedContentContainer(this); 103 delete this; 104} 105 106// Overridden from TabContentsDelegate: 107void BlockedContentContainer::OpenURLFromTab(TabContents* source, 108 const GURL& url, 109 const GURL& referrer, 110 WindowOpenDisposition disposition, 111 PageTransition::Type transition) { 112 owner_->OpenURL(url, referrer, disposition, transition); 113} 114 115void BlockedContentContainer::AddNewContents(TabContents* source, 116 TabContents* new_contents, 117 WindowOpenDisposition disposition, 118 const gfx::Rect& initial_position, 119 bool user_gesture) { 120 owner_->AddOrBlockNewContents( 121 new_contents, disposition, initial_position, user_gesture); 122} 123 124void BlockedContentContainer::CloseContents(TabContents* source) { 125 for (BlockedContents::iterator i(blocked_contents_.begin()); 126 i != blocked_contents_.end(); ++i) { 127 TabContents* tab_contents = i->tab_contents; 128 if (tab_contents == source) { 129 tab_contents->set_delegate(NULL); 130 blocked_contents_.erase(i); 131 delete tab_contents; 132 break; 133 } 134 } 135} 136 137void BlockedContentContainer::MoveContents(TabContents* source, 138 const gfx::Rect& new_bounds) { 139 for (BlockedContents::iterator i(blocked_contents_.begin()); 140 i != blocked_contents_.end(); ++i) { 141 if (i->tab_contents == source) { 142 i->bounds = new_bounds; 143 break; 144 } 145 } 146} 147 148bool BlockedContentContainer::IsPopup(const TabContents* source) const { 149 // Assume everything added is a popup. This may turn out to be wrong, but 150 // callers don't cache this information so it should be fine if the value ends 151 // up changing. 152 return true; 153} 154 155TabContents* BlockedContentContainer::GetConstrainingContents( 156 TabContents* source) { 157 return owner_; 158} 159