19ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 29ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 39ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// found in the LICENSE file. 49ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 59ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h" 69ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/content_settings/host_content_settings_map.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/content_settings/tab_specific_content_settings.h" 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/profiles/profile.h" 1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/blocked_content/blocked_window_params.h" 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "chrome/browser/ui/browser_navigator.h" 13558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/ui/tabs/tab_strip_model.h" 1458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "chrome/common/render_messages.h" 159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "content/public/browser/navigation_controller.h" 169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "content/public/browser/navigation_details.h" 179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "content/public/browser/navigation_entry.h" 183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/render_view_host.h" 199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "content/public/browser/web_contents.h" 209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "content/public/browser/web_contents_delegate.h" 2158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "third_party/WebKit/public/web/WebWindowFeatures.h" 2258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_ANDROID) 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/android/tab_model/tab_model_list.h" 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using blink::WebWindowFeatures; 289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const size_t kMaximumNumberOfPopups = 25; 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochDEFINE_WEB_CONTENTS_USER_DATA_KEY(PopupBlockerTabHelper); 329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 3358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdochstruct PopupBlockerTabHelper::BlockedRequest { 3458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch BlockedRequest(const chrome::NavigateParams& params, 3558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const WebWindowFeatures& window_features) 3658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch : params(params), window_features(window_features) {} 3758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 3858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch chrome::NavigateParams params; 3958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch WebWindowFeatures window_features; 4058e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch}; 4158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch 429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochPopupBlockerTabHelper::PopupBlockerTabHelper( 439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch content::WebContents* web_contents) 449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch : content::WebContentsObserver(web_contents) { 459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochPopupBlockerTabHelper::~PopupBlockerTabHelper() { 489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid PopupBlockerTabHelper::DidNavigateMainFrame( 519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const content::LoadCommittedDetails& details, 529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const content::FrameNavigateParams& params) { 539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Clear all page actions, blocked content notifications and browser actions 549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // for this tab, unless this is an in-page navigation. 559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (details.is_in_page) 569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Close blocked popups. 599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!blocked_popups_.IsEmpty()) { 609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch blocked_popups_.Clear(); 619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch PopupNotificationVisibilityChanged(false); 629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid PopupBlockerTabHelper::PopupNotificationVisibilityChanged( 669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch bool visible) { 679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!web_contents()->IsBeingDestroyed()) { 689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch TabSpecificContentSettings::FromWebContents(web_contents())-> 699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch SetPopupsBlocked(visible); 709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochbool PopupBlockerTabHelper::MaybeBlockPopup( 7458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const chrome::NavigateParams& params, 7558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch const WebWindowFeatures& window_features) { 769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // A page can't spawn popups (or do anything else, either) until its load 779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // commits, so when we reach here, the popup was spawned by the 789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // NavigationController's last committed entry, not the active entry. For 799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // example, if a page opens a popup in an onunload() handler, then the active 809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // entry is the page to be loaded as we navigate away from the unloading 819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // page. For this reason, we can't use GetURL() to get the opener URL, 829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // because it returns the active entry. 839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch content::NavigationEntry* entry = 849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch web_contents()->GetController().GetLastCommittedEntry(); 859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch GURL creator = entry ? entry->GetVirtualURL() : GURL(); 869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch Profile* profile = 879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch Profile::FromBrowserContext(web_contents()->GetBrowserContext()); 889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (creator.is_valid() && 909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch profile->GetHostContentSettingsMap()->GetContentSetting( 919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch creator, creator, CONTENT_SETTINGS_TYPE_POPUPS, std::string()) == 929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CONTENT_SETTING_ALLOW) { 939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return false; 949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } else { 9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (blocked_popups_.size() < kMaximumNumberOfPopups) { 9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) blocked_popups_.Add(new BlockedRequest(params, window_features)); 9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) TabSpecificContentSettings::FromWebContents(web_contents())-> 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS); 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return true; 1019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 1029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 1039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void PopupBlockerTabHelper::AddBlockedPopup(const BlockedWindowParams& params) { 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) chrome::NavigateParams nav_params = 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) params.CreateNavigateParams(web_contents()); 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (blocked_popups_.size() < kMaximumNumberOfPopups) { 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) blocked_popups_.Add(new BlockedRequest(nav_params, params.features())); 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) TabSpecificContentSettings::FromWebContents(web_contents())-> 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) OnContentBlocked(CONTENT_SETTINGS_TYPE_POPUPS); 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 114558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid PopupBlockerTabHelper::ShowBlockedPopup(int32 id) { 11658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch BlockedRequest* popup = blocked_popups_.Lookup(id); 11758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (!popup) 1189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We set user_gesture to true here, so the new popup gets correctly focused. 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) popup->params.user_gesture = true; 121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(OS_ANDROID) 122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) TabModelList::HandlePopupNavigation(&popup->params); 123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#else 12458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch chrome::Navigate(&popup->params); 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif 12658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch if (popup->params.target_contents) { 12758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch popup->params.target_contents->Send(new ChromeViewMsg_SetWindowFeatures( 12858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch popup->params.target_contents->GetRoutingID(), popup->window_features)); 12958e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch } 1309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch blocked_popups_.Remove(id); 1319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (blocked_popups_.IsEmpty()) 1329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch PopupNotificationVisibilityChanged(false); 1339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 1349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochsize_t PopupBlockerTabHelper::GetBlockedPopupsCount() const { 1369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return blocked_popups_.size(); 1379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 1389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)PopupBlockerTabHelper::PopupIdMap 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PopupBlockerTabHelper::GetBlockedPopupRequests() { 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PopupIdMap result; 14258e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch for (IDMap<BlockedRequest, IDMapOwnPointer>::const_iterator iter( 14358e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch &blocked_popups_); 14458e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch !iter.IsAtEnd(); 14558e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch iter.Advance()) { 14658e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch result[iter.GetCurrentKey()] = iter.GetCurrentValue()->params.url; 14758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch } 14858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch return result; 1499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 150