Home | History | Annotate | Download | only in blocked_content
      1 // Copyright (c) 2012 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/ui/blocked_content/blocked_content_container.h"
      6 
      7 #include "base/logging.h"
      8 #include "chrome/browser/favicon/favicon_tab_helper.h"
      9 #include "chrome/browser/ui/blocked_content/blocked_content_tab_helper.h"
     10 #include "content/public/browser/web_contents.h"
     11 #include "ui/gfx/rect.h"
     12 
     13 using content::OpenURLParams;
     14 using content::WebContents;
     15 
     16 // static
     17 const size_t BlockedContentContainer::kImpossibleNumberOfPopups = 30;
     18 
     19 struct BlockedContentContainer::BlockedContent {
     20   BlockedContent(WebContents* web_contents,
     21                  WindowOpenDisposition disposition,
     22                  const gfx::Rect& bounds,
     23                  bool user_gesture)
     24       : web_contents(web_contents),
     25         disposition(disposition),
     26         bounds(bounds),
     27         user_gesture(user_gesture) {
     28   }
     29 
     30   WebContents* web_contents;
     31   WindowOpenDisposition disposition;
     32   gfx::Rect bounds;
     33   bool user_gesture;
     34 };
     35 
     36 BlockedContentContainer::BlockedContentContainer(content::WebContents* owner)
     37     : owner_(owner) {
     38 }
     39 
     40 BlockedContentContainer::~BlockedContentContainer() {
     41   Clear();
     42 }
     43 
     44 void BlockedContentContainer::AddWebContents(content::WebContents* web_contents,
     45                                              WindowOpenDisposition disposition,
     46                                              const gfx::Rect& bounds,
     47                                              bool user_gesture) {
     48   if (blocked_contents_.size() == (kImpossibleNumberOfPopups - 1)) {
     49     delete web_contents;
     50     VLOG(1) << "Warning: Renderer is sending more popups to us than should be "
     51                "possible. Renderer compromised?";
     52     return;
     53   }
     54 
     55   blocked_contents_.push_back(
     56       BlockedContent(web_contents, disposition, bounds, user_gesture));
     57   web_contents->SetDelegate(this);
     58 
     59   BlockedContentTabHelper::CreateForWebContents(web_contents);
     60   // Various UI parts assume the ability to retrieve favicons from blocked
     61   // content.
     62   FaviconTabHelper::CreateForWebContents(web_contents);
     63   BlockedContentTabHelper::FromWebContents(web_contents)->set_delegate(this);
     64 
     65   // Since the new web_contents will not be shown, call WasHidden to change
     66   // its status on both RenderViewHost and RenderView.
     67   web_contents->WasHidden();
     68 }
     69 
     70 void BlockedContentContainer::LaunchForContents(
     71     content::WebContents* web_contents) {
     72   // Open the popup.
     73   for (BlockedContents::iterator i = blocked_contents_.begin();
     74        i != blocked_contents_.end(); ++i) {
     75     if (i->web_contents == web_contents) {
     76       // To support the owner blocking the content again we copy and erase
     77       // before attempting to add.
     78       BlockedContent content(*i);
     79       blocked_contents_.erase(i);
     80       i = blocked_contents_.end();
     81       web_contents->SetDelegate(NULL);
     82       BlockedContentTabHelper::FromWebContents(web_contents)->
     83           set_delegate(NULL);
     84       // We needn't call WasShown to change its status because the
     85       // WebContents::AddNewContents will do it.
     86       WebContentsDelegate* delegate = owner_->GetDelegate();
     87       if (delegate) {
     88         delegate->AddNewContents(owner_,
     89                                  web_contents,
     90                                  content.disposition,
     91                                  content.bounds,
     92                                  content.user_gesture,
     93                                  NULL);
     94       }
     95       break;
     96     }
     97   }
     98 }
     99 
    100 size_t BlockedContentContainer::GetBlockedContentsCount() const {
    101   return blocked_contents_.size();
    102 }
    103 
    104 void BlockedContentContainer::GetBlockedContents(
    105     std::vector<WebContents*>* blocked_contents) const {
    106   DCHECK(blocked_contents);
    107   for (BlockedContents::const_iterator i = blocked_contents_.begin();
    108        i != blocked_contents_.end(); ++i)
    109     blocked_contents->push_back(i->web_contents);
    110 }
    111 
    112 void BlockedContentContainer::Clear() {
    113   for (BlockedContents::iterator i = blocked_contents_.begin();
    114        i != blocked_contents_.end(); ++i) {
    115     WebContents* web_contents = i->web_contents;
    116     web_contents->SetDelegate(NULL);
    117     BlockedContentTabHelper::FromWebContents(web_contents)->set_delegate(NULL);
    118     delete web_contents;
    119   }
    120   blocked_contents_.clear();
    121 }
    122 
    123 // Overridden from content::WebContentsDelegate:
    124 
    125 WebContents* BlockedContentContainer::OpenURLFromTab(
    126     WebContents* source,
    127     const OpenURLParams& params) {
    128   return owner_->OpenURL(params);
    129 }
    130 
    131 void BlockedContentContainer::AddNewContents(WebContents* source,
    132                                              WebContents* new_contents,
    133                                              WindowOpenDisposition disposition,
    134                                              const gfx::Rect& initial_position,
    135                                              bool user_gesture,
    136                                              bool* was_blocked) {
    137   WebContentsDelegate* delegate = owner_->GetDelegate();
    138   if (delegate) {
    139     delegate->AddNewContents(owner_, new_contents, disposition,
    140                              initial_position, user_gesture, was_blocked);
    141   }
    142 }
    143 
    144 void BlockedContentContainer::CloseContents(WebContents* source) {
    145   for (BlockedContents::iterator i = blocked_contents_.begin();
    146        i != blocked_contents_.end(); ++i) {
    147     WebContents* web_contents = i->web_contents;
    148     if (web_contents == source) {
    149       web_contents->SetDelegate(NULL);
    150       BlockedContentTabHelper::FromWebContents(web_contents)->
    151           set_delegate(NULL);
    152       blocked_contents_.erase(i);
    153       delete web_contents;
    154       break;
    155     }
    156   }
    157 }
    158 
    159 void BlockedContentContainer::MoveContents(WebContents* source,
    160                                            const gfx::Rect& new_bounds) {
    161   for (BlockedContents::iterator i = blocked_contents_.begin();
    162        i != blocked_contents_.end(); ++i) {
    163     if (i->web_contents == source) {
    164       i->bounds = new_bounds;
    165       break;
    166     }
    167   }
    168 }
    169 
    170 bool BlockedContentContainer::IsPopupOrPanel(const WebContents* source) const {
    171   // Assume everything added is a popup. This may turn out to be wrong, but
    172   // callers don't cache this information so it should be fine if the value ends
    173   // up changing.
    174   return true;
    175 }
    176 
    177 bool BlockedContentContainer::ShouldSuppressDialogs() {
    178   // Suppress JavaScript dialogs when inside a constrained popup window (because
    179   // that activates them and breaks them out of the constrained window jail).
    180   return true;
    181 }
    182 
    183 content::WebContents* BlockedContentContainer::GetConstrainingWebContents(
    184     content::WebContents* source) {
    185   return owner_;
    186 }
    187