Home | History | Annotate | Download | only in browser
      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 {
     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 
     30 BlockedContentContainer::BlockedContentContainer(TabContents* owner)
     31     : owner_(owner) {
     32 }
     33 
     34 BlockedContentContainer::~BlockedContentContainer() {}
     35 
     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 
     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 
     82 size_t BlockedContentContainer::GetBlockedContentsCount() const {
     83   return blocked_contents_.size();
     84 }
     85 
     86 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 
     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:
    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 
    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 
    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 
    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 
    148 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 
    155 TabContents* BlockedContentContainer::GetConstrainingContents(
    156     TabContents* source) {
    157   return owner_;
    158 }
    159