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