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