1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/blocked_content/popup_blocker.h"
#include <string>
#include "base/check.h"
#include "base/command_line.h"
#include "components/blocked_content/popup_blocker_tab_helper.h"
#include "components/blocked_content/popup_navigation_delegate.h"
#include "components/blocked_content/safe_browsing_triggered_popup_blocker.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/embedder_support/switches.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h"
namespace blocked_content {
namespace {
content::Page& GetSourcePageForPopup(
const content::OpenURLParams* open_url_params,
content::WebContents* web_contents) {
if (open_url_params) {
content::RenderFrameHost* source = content::RenderFrameHost::FromID(
open_url_params->source_render_process_id,
open_url_params->source_render_frame_id);
if (source)
return source->GetPage();
}
// When there's no source RenderFrameHost, attribute the popup to the primary
// page.
return web_contents->GetPrimaryPage();
}
// If the popup should be blocked, returns the reason why it was blocked.
// Otherwise returns kNotBlocked.
PopupBlockType ShouldBlockPopup(content::WebContents* web_contents,
const GURL* opener_url,
bool user_gesture,
const content::OpenURLParams* open_url_params,
HostContentSettingsMap* settings_map) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
embedder_support::kDisablePopupBlocking)) {
return PopupBlockType::kNotBlocked;
}
// If an explicit opener is not given, use the current committed load in this
// web contents. This is because A page can't spawn popups (or do anything
// else, either) until its load commits, so when we reach here, the popup was
// spawned by the NavigationController's last committed entry, not the active
// entry. For example, if a page opens a popup in an onunload() handler, then
// the active entry is the page to be loaded as we navigate away from the
// unloading page.
const GURL& url =
opener_url ? *opener_url : web_contents->GetLastCommittedURL();
ContentSetting cs;
if (url.is_valid()) {
cs = settings_map->GetContentSetting(url, url, ContentSettingsType::POPUPS);
} else {
cs = settings_map->GetDefaultContentSetting(ContentSettingsType::POPUPS,
nullptr);
}
if (cs == CONTENT_SETTING_ALLOW)
return PopupBlockType::kNotBlocked;
if (!user_gesture)
return PopupBlockType::kNoGesture;
// This is trusted user action (e.g. shift-click), so make sure it is not
// blocked.
if (open_url_params &&
open_url_params->triggering_event_info !=
blink::mojom::TriggeringEventInfo::kFromUntrustedEvent) {
return PopupBlockType::kNotBlocked;
}
auto* safe_browsing_blocker =
SafeBrowsingTriggeredPopupBlocker::FromWebContents(web_contents);
if (safe_browsing_blocker &&
safe_browsing_blocker->ShouldApplyAbusivePopupBlocker(
GetSourcePageForPopup(open_url_params, web_contents))) {
return PopupBlockType::kAbusive;
}
return PopupBlockType::kNotBlocked;
}
} // namespace
bool ConsiderForPopupBlocking(WindowOpenDisposition disposition) {
return disposition == WindowOpenDisposition::NEW_POPUP ||
disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB ||
disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB ||
disposition == WindowOpenDisposition::NEW_WINDOW;
}
std::unique_ptr<PopupNavigationDelegate> MaybeBlockPopup(
content::WebContents* web_contents,
const GURL* opener_url,
std::unique_ptr<PopupNavigationDelegate> delegate,
const content::OpenURLParams* open_url_params,
const blink::mojom::WindowFeatures& window_features,
HostContentSettingsMap* settings_map) {
DCHECK(web_contents);
DCHECK(!open_url_params ||
open_url_params->user_gesture == delegate->GetOriginalUserGesture());
PopupBlockerTabHelper::LogAction(PopupBlockerTabHelper::Action::kInitiated);
// Check |popup_blocker| first since it is cheaper than ShouldBlockPopup().
auto* popup_blocker = PopupBlockerTabHelper::FromWebContents(web_contents);
if (!popup_blocker)
return delegate;
PopupBlockType block_type = ShouldBlockPopup(
web_contents, opener_url, delegate->GetOriginalUserGesture(),
open_url_params, settings_map);
if (block_type == PopupBlockType::kNotBlocked)
return delegate;
popup_blocker->AddBlockedPopup(std::move(delegate), window_features,
block_type);
return nullptr;
}
} // namespace blocked_content
|