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/blocked_content/blocked_window_params.h"
     12 #include "chrome/browser/ui/browser_navigator.h"
     13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     14 #include "chrome/common/render_messages.h"
     15 #include "content/public/browser/navigation_controller.h"
     16 #include "content/public/browser/navigation_details.h"
     17 #include "content/public/browser/navigation_entry.h"
     18 #include "content/public/browser/render_view_host.h"
     19 #include "content/public/browser/web_contents.h"
     20 #include "content/public/browser/web_contents_delegate.h"
     21 #include "content/public/browser/web_contents_view.h"
     22 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
     23 
     24 #if defined(OS_ANDROID)
     25 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
     26 #endif
     27 
     28 using blink::WebWindowFeatures;
     29 
     30 const size_t kMaximumNumberOfPopups = 25;
     31 
     32 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupBlockerTabHelper);
     33 
     34 struct PopupBlockerTabHelper::BlockedRequest {
     35   BlockedRequest(const chrome::NavigateParams& params,
     36                  const WebWindowFeatures& window_features)
     37       : params(params), window_features(window_features) {}
     38 
     39   chrome::NavigateParams params;
     40   WebWindowFeatures window_features;
     41 };
     42 
     43 PopupBlockerTabHelper::PopupBlockerTabHelper(
     44     content::WebContents* web_contents)
     45     : content::WebContentsObserver(web_contents) {
     46 }
     47 
     48 PopupBlockerTabHelper::~PopupBlockerTabHelper() {
     49 }
     50 
     51 void PopupBlockerTabHelper::DidNavigateMainFrame(
     52     const content::LoadCommittedDetails& details,
     53     const content::FrameNavigateParams& params) {
     54   // Clear all page actions, blocked content notifications and browser actions
     55   // for this tab, unless this is an in-page navigation.
     56   if (details.is_in_page)
     57     return;
     58 
     59   // Close blocked popups.
     60   if (!blocked_popups_.IsEmpty()) {
     61     blocked_popups_.Clear();
     62     PopupNotificationVisibilityChanged(false);
     63   }
     64 }
     65 
     66 void PopupBlockerTabHelper::PopupNotificationVisibilityChanged(
     67     bool visible) {
     68   if (!web_contents()->IsBeingDestroyed()) {
     69     TabSpecificContentSettings::FromWebContents(web_contents())->
     70         SetPopupsBlocked(visible);
     71   }
     72 }
     73 
     74 bool PopupBlockerTabHelper::MaybeBlockPopup(
     75     const chrome::NavigateParams& params,
     76     const WebWindowFeatures& window_features) {
     77   // A page can't spawn popups (or do anything else, either) until its load
     78   // commits, so when we reach here, the popup was spawned by the
     79   // NavigationController's last committed entry, not the active entry.  For
     80   // example, if a page opens a popup in an onunload() handler, then the active
     81   // entry is the page to be loaded as we navigate away from the unloading
     82   // page.  For this reason, we can't use GetURL() to get the opener URL,
     83   // because it returns the active entry.
     84   content::NavigationEntry* entry =
     85       web_contents()->GetController().GetLastCommittedEntry();
     86   GURL creator = entry ? entry->GetVirtualURL() : GURL();
     87   Profile* profile =
     88       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
     89 
     90   if (creator.is_valid() &&
     91       profile->GetHostContentSettingsMap()->GetContentSetting(
     92           creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) ==
     93           CONTENT_SETTING_ALLOW) {
     94     return false;
     95   } else {
     96     if (blocked_popups_.size() < kMaximumNumberOfPopups) {
     97       blocked_popups_.Add(new BlockedRequest(params, window_features));
     98       TabSpecificContentSettings::FromWebContents(web_contents())->
     99           OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS);
    100     }
    101     return true;
    102   }
    103 }
    104 
    105 void PopupBlockerTabHelper::AddBlockedPopup(const BlockedWindowParams& params) {
    106   chrome::NavigateParams nav_params =
    107       params.CreateNavigateParams(web_contents());
    108 
    109   if (blocked_popups_.size() < kMaximumNumberOfPopups) {
    110     blocked_popups_.Add(new BlockedRequest(nav_params, params.features()));
    111     TabSpecificContentSettings::FromWebContents(web_contents())->
    112         OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS);
    113   }
    114 }
    115 
    116 void PopupBlockerTabHelper::ShowBlockedPopup(int32 id) {
    117   BlockedRequest* popup = blocked_popups_.Lookup(id);
    118   if (!popup)
    119     return;
    120 #if defined(OS_ANDROID)
    121   TabModelList::HandlePopupNavigation(&popup->params);
    122 #else
    123   chrome::Navigate(&popup->params);
    124 #endif
    125   if (popup->params.target_contents) {
    126     popup->params.target_contents->Send(new ChromeViewMsg_SetWindowFeatures(
    127         popup->params.target_contents->GetRoutingID(), popup->window_features));
    128   }
    129   blocked_popups_.Remove(id);
    130   if (blocked_popups_.IsEmpty())
    131     PopupNotificationVisibilityChanged(false);
    132 }
    133 
    134 size_t PopupBlockerTabHelper::GetBlockedPopupsCount() const {
    135   return blocked_popups_.size();
    136 }
    137 
    138 PopupBlockerTabHelper::PopupIdMap
    139     PopupBlockerTabHelper::GetBlockedPopupRequests() {
    140   PopupIdMap result;
    141   for (IDMap<BlockedRequest, IDMapOwnPointer>::const_iterator iter(
    142            &blocked_popups_);
    143        !iter.IsAtEnd();
    144        iter.Advance()) {
    145     result[iter.GetCurrentKey()] = iter.GetCurrentValue()->params.url;
    146   }
    147   return result;
    148 }
    149