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