Home | History | Annotate | Download | only in blocked_content
      1 // Copyright 2013 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/popup_blocker_tab_helper.h"
      6 
      7 #include "chrome/browser/chrome_notification_types.h"
      8 #include "chrome/browser/content_settings/host_content_settings_map.h"
      9 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/browser/ui/browser_navigator.h"
     12 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     13 #include "chrome/common/render_messages.h"
     14 #include "content/public/browser/navigation_controller.h"
     15 #include "content/public/browser/navigation_details.h"
     16 #include "content/public/browser/navigation_entry.h"
     17 #include "content/public/browser/render_view_host.h"
     18 #include "content/public/browser/web_contents.h"
     19 #include "content/public/browser/web_contents_delegate.h"
     20 #include "content/public/browser/web_contents_view.h"
     21 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
     22 
     23 using WebKit::WebWindowFeatures;
     24 
     25 const size_t kMaximumNumberOfPopups = 25;
     26 
     27 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupBlockerTabHelper);
     28 
     29 struct PopupBlockerTabHelper::BlockedRequest {
     30   BlockedRequest(const chrome::NavigateParams& params,
     31                  const WebWindowFeatures& window_features)
     32       : params(params), window_features(window_features) {}
     33 
     34   chrome::NavigateParams params;
     35   WebWindowFeatures window_features;
     36 };
     37 
     38 PopupBlockerTabHelper::PopupBlockerTabHelper(
     39     content::WebContents* web_contents)
     40     : content::WebContentsObserver(web_contents) {
     41 }
     42 
     43 PopupBlockerTabHelper::~PopupBlockerTabHelper() {
     44 }
     45 
     46 void PopupBlockerTabHelper::DidNavigateMainFrame(
     47     const content::LoadCommittedDetails& details,
     48     const content::FrameNavigateParams& params) {
     49   // Clear all page actions, blocked content notifications and browser actions
     50   // for this tab, unless this is an in-page navigation.
     51   if (details.is_in_page)
     52     return;
     53 
     54   // Close blocked popups.
     55   if (!blocked_popups_.IsEmpty()) {
     56     blocked_popups_.Clear();
     57     PopupNotificationVisibilityChanged(false);
     58   }
     59 }
     60 
     61 void PopupBlockerTabHelper::PopupNotificationVisibilityChanged(
     62     bool visible) {
     63   if (!web_contents()->IsBeingDestroyed()) {
     64     TabSpecificContentSettings::FromWebContents(web_contents())->
     65         SetPopupsBlocked(visible);
     66   }
     67 }
     68 
     69 bool PopupBlockerTabHelper::MaybeBlockPopup(
     70     const chrome::NavigateParams& params,
     71     const WebWindowFeatures& window_features) {
     72   // A page can't spawn popups (or do anything else, either) until its load
     73   // commits, so when we reach here, the popup was spawned by the
     74   // NavigationController's last committed entry, not the active entry.  For
     75   // example, if a page opens a popup in an onunload() handler, then the active
     76   // entry is the page to be loaded as we navigate away from the unloading
     77   // page.  For this reason, we can't use GetURL() to get the opener URL,
     78   // because it returns the active entry.
     79   content::NavigationEntry* entry =
     80       web_contents()->GetController().GetLastCommittedEntry();
     81   GURL creator = entry ? entry->GetVirtualURL() : GURL();
     82   Profile* profile =
     83       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
     84 
     85   if (creator.is_valid() &&
     86       profile->GetHostContentSettingsMap()->GetContentSetting(
     87           creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) ==
     88           CONTENT_SETTING_ALLOW) {
     89     return false;
     90   } else {
     91     if (blocked_popups_.size() < kMaximumNumberOfPopups) {
     92       blocked_popups_.Add(new BlockedRequest(params, window_features));
     93       TabSpecificContentSettings::FromWebContents(web_contents())->
     94           OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, std::string());
     95     }
     96     return true;
     97   }
     98 }
     99 
    100 void PopupBlockerTabHelper::AddBlockedPopup(
    101     const GURL& target_url,
    102     const content::Referrer& referrer,
    103     WindowOpenDisposition disposition,
    104     const WebWindowFeatures& features,
    105     bool user_gesture,
    106     bool opener_suppressed) {
    107   GURL popup_url(target_url);
    108   content::RenderViewHost::FilterURL(
    109       web_contents()->GetRenderProcessHost(), false, &popup_url);
    110   chrome::NavigateParams nav_params(
    111       Profile::FromBrowserContext(web_contents()->GetBrowserContext()),
    112       popup_url,
    113       content::PAGE_TRANSITION_LINK);
    114   nav_params.referrer = referrer;
    115   nav_params.source_contents = web_contents();
    116   nav_params.is_renderer_initiated = true;
    117   nav_params.tabstrip_add_types = TabStripModel::ADD_ACTIVE;
    118   nav_params.window_action = chrome::NavigateParams::SHOW_WINDOW;
    119   nav_params.user_gesture = user_gesture;
    120   nav_params.should_set_opener = !opener_suppressed;
    121   web_contents()->GetView()->GetContainerBounds(&nav_params.window_bounds);
    122   if (features.xSet)
    123     nav_params.window_bounds.set_x(features.x);
    124   if (features.ySet)
    125     nav_params.window_bounds.set_y(features.y);
    126   if (features.widthSet)
    127     nav_params.window_bounds.set_width(features.width);
    128   if (features.heightSet)
    129     nav_params.window_bounds.set_height(features.height);
    130 
    131   // Compare RenderViewImpl::show().
    132   if (!user_gesture && disposition != NEW_BACKGROUND_TAB)
    133     nav_params.disposition = NEW_POPUP;
    134   else
    135     nav_params.disposition = disposition;
    136 
    137   if (blocked_popups_.size() < kMaximumNumberOfPopups) {
    138     blocked_popups_.Add(new BlockedRequest(nav_params, features));
    139     TabSpecificContentSettings::FromWebContents(web_contents())->
    140         OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS, std::string());
    141   }
    142 }
    143 
    144 void PopupBlockerTabHelper::ShowBlockedPopup(int32 id) {
    145   BlockedRequest* popup = blocked_popups_.Lookup(id);
    146   if (!popup)
    147     return;
    148   chrome::Navigate(&popup->params);
    149   if (popup->params.target_contents) {
    150     popup->params.target_contents->Send(new ChromeViewMsg_SetWindowFeatures(
    151         popup->params.target_contents->GetRoutingID(), popup->window_features));
    152   }
    153   blocked_popups_.Remove(id);
    154   if (blocked_popups_.IsEmpty())
    155     PopupNotificationVisibilityChanged(false);
    156 }
    157 
    158 size_t PopupBlockerTabHelper::GetBlockedPopupsCount() const {
    159   return blocked_popups_.size();
    160 }
    161 
    162 std::map<int32, GURL> PopupBlockerTabHelper::GetBlockedPopupRequests() {
    163   std::map<int32, GURL> result;
    164   for (IDMap<BlockedRequest, IDMapOwnPointer>::const_iterator iter(
    165            &blocked_popups_);
    166        !iter.IsAtEnd();
    167        iter.Advance()) {
    168     result[iter.GetCurrentKey()] = iter.GetCurrentValue()->params.url;
    169   }
    170   return result;
    171 }
    172