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
11 const size_t BlockedContentContainer::kImpossibleNumberOfPopups = 30;
12
13 struct BlockedContentContainer::BlockedContent {
BlockedContentBlockedContentContainer::BlockedContent14 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
BlockedContentContainer(TabContents * owner)30 BlockedContentContainer::BlockedContentContainer(TabContents* owner)
31 : owner_(owner) {
32 }
33
~BlockedContentContainer()34 BlockedContentContainer::~BlockedContentContainer() {}
35
AddTabContents(TabContents * tab_contents,WindowOpenDisposition disposition,const gfx::Rect & bounds,bool user_gesture)36 void 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
LaunchForContents(TabContents * tab_contents)57 void 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
GetBlockedContentsCount() const82 size_t BlockedContentContainer::GetBlockedContentsCount() const {
83 return blocked_contents_.size();
84 }
85
GetBlockedContents(std::vector<TabContents * > * blocked_contents) const86 void 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
Destroy()94 void 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:
OpenURLFromTab(TabContents * source,const GURL & url,const GURL & referrer,WindowOpenDisposition disposition,PageTransition::Type transition)107 void 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
AddNewContents(TabContents * source,TabContents * new_contents,WindowOpenDisposition disposition,const gfx::Rect & initial_position,bool user_gesture)115 void 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
CloseContents(TabContents * source)124 void 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
MoveContents(TabContents * source,const gfx::Rect & new_bounds)137 void 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
IsPopup(const TabContents * source) const148 bool 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
GetConstrainingContents(TabContents * source)155 TabContents* BlockedContentContainer::GetConstrainingContents(
156 TabContents* source) {
157 return owner_;
158 }
159