123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h"
- #include <memory>
- #include <utility>
- #include "android_webview/browser/aw_browser_context.h"
- #include "android_webview/browser/aw_browser_process.h"
- #include "android_webview/browser/aw_contents_client_bridge.h"
- #include "android_webview/browser/network_service/aw_web_resource_request.h"
- #include "android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h"
- #include "base/feature_list.h"
- #include "base/metrics/histogram_macros.h"
- #include "components/prefs/pref_service.h"
- #include "components/safe_browsing/content/browser/threat_details.h"
- #include "components/safe_browsing/content/browser/triggers/trigger_manager.h"
- #include "components/safe_browsing/core/common/features.h"
- #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
- #include "components/safe_browsing/core/common/utils.h"
- #include "components/security_interstitials/content/security_interstitial_controller_client.h"
- #include "components/security_interstitials/content/settings_page_helper.h"
- #include "components/security_interstitials/content/unsafe_resource_util.h"
- #include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
- #include "components/security_interstitials/core/safe_browsing_quiet_error_ui.h"
- #include "components/security_interstitials/core/unsafe_resource.h"
- #include "content/public/browser/navigation_entry.h"
- #include "content/public/browser/navigation_handle.h"
- #include "content/public/browser/storage_partition.h"
- #include "content/public/browser/web_contents.h"
- #include "net/base/net_errors.h"
- using content::WebContents;
- using security_interstitials::BaseSafeBrowsingErrorUI;
- using security_interstitials::SafeBrowsingQuietErrorUI;
- using security_interstitials::SecurityInterstitialControllerClient;
- namespace android_webview {
- AwSafeBrowsingBlockingPage::AwSafeBrowsingBlockingPage(
- AwSafeBrowsingUIManager* ui_manager,
- WebContents* web_contents,
- const GURL& main_frame_url,
- const UnsafeResourceList& unsafe_resources,
- std::unique_ptr<SecurityInterstitialControllerClient> controller_client,
- const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
- ErrorUiType errorUiType,
- std::unique_ptr<AwWebResourceRequest> resource_request)
- : BaseBlockingPage(ui_manager,
- web_contents,
- main_frame_url,
- unsafe_resources,
- std::move(controller_client),
- display_options),
- threat_details_in_progress_(false),
- resource_request_(std::move(resource_request)) {
- if (errorUiType == ErrorUiType::QUIET_SMALL ||
- errorUiType == ErrorUiType::QUIET_GIANT) {
- set_sb_error_ui(std::make_unique<SafeBrowsingQuietErrorUI>(
- unsafe_resources[0].url, main_frame_url,
- GetInterstitialReason(unsafe_resources), display_options,
- ui_manager->app_locale(), base::Time::NowFromSystemTime(), controller(),
- errorUiType == ErrorUiType::QUIET_GIANT));
- }
- if (unsafe_resources.size() == 1 &&
- ShouldReportThreatDetails(unsafe_resources[0].threat_type)) {
- AwBrowserContext* aw_browser_context =
- AwBrowserContext::FromWebContents(web_contents);
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
- aw_browser_context->GetDefaultStoragePartition()
- ->GetURLLoaderFactoryForBrowserProcess();
- // TODO(timvolodine): create a proper history service; currently the
- // HistoryServiceFactory lives in the chrome/ layer and relies on Profile
- // which we don't have in Android WebView (crbug.com/731744).
- threat_details_in_progress_ =
- AwBrowserProcess::GetInstance()
- ->GetSafeBrowsingTriggerManager()
- ->StartCollectingThreatDetails(
- safe_browsing::TriggerType::SECURITY_INTERSTITIAL, web_contents,
- unsafe_resources[0], url_loader_factory,
- /*history_service*/ nullptr,
- /*referrer_chain_provider*/ nullptr,
- sb_error_ui()->get_error_display_options());
- }
- }
- AwSafeBrowsingBlockingPage* AwSafeBrowsingBlockingPage::CreateBlockingPage(
- AwSafeBrowsingUIManager* ui_manager,
- content::WebContents* web_contents,
- const GURL& main_frame_url,
- const UnsafeResource& unsafe_resource,
- std::unique_ptr<AwWebResourceRequest> resource_request) {
- // Log the request destination that triggers the safe browsing blocking page.
- UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.BlockingPage.RequestDestination",
- unsafe_resource.request_destination);
- const UnsafeResourceList unsafe_resources{unsafe_resource};
- AwBrowserContext* browser_context =
- AwBrowserContext::FromWebContents(web_contents);
- PrefService* pref_service = browser_context->GetPrefService();
- // TODO(crbug.com/1134678): Set is_enhanced_protection_message_enabled once
- // enhanced protection is supported on aw.
- BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options =
- BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
- IsMainPageLoadBlocked(unsafe_resources),
- safe_browsing::IsExtendedReportingOptInAllowed(*pref_service),
- browser_context->IsOffTheRecord(),
- safe_browsing::IsExtendedReportingEnabled(*pref_service),
- safe_browsing::IsExtendedReportingPolicyManaged(*pref_service),
- safe_browsing::IsEnhancedProtectionEnabled(*pref_service),
- pref_service->GetBoolean(::prefs::kSafeBrowsingProceedAnywayDisabled),
- false, // should_open_links_in_new_tab
- false, // always_show_back_to_safety
- false, // is_enhanced_protection_message_enabled
- safe_browsing::IsSafeBrowsingPolicyManaged(*pref_service),
- "cpn_safe_browsing_wv"); // help_center_article_link
- ErrorUiType errorType =
- static_cast<ErrorUiType>(ui_manager->GetErrorUiType(web_contents));
- // TODO(carlosil): This logic is necessary to support committed and non
- // committed interstitials, it can be cleaned up when removing non-committed
- // interstitials.
- content::NavigationEntry* entry =
- GetNavigationEntryForResource(unsafe_resource);
- GURL url =
- (main_frame_url.is_empty() && entry) ? entry->GetURL() : main_frame_url;
- // TODO(crbug.com/1134678): Set settings_page_helper once enhanced protection
- // is supported on aw.
- return new AwSafeBrowsingBlockingPage(
- ui_manager, web_contents, url, unsafe_resources,
- CreateControllerClient(web_contents, unsafe_resources, ui_manager,
- pref_service, /*settings_page_helper*/ nullptr),
- display_options, errorType, std::move(resource_request));
- }
- AwSafeBrowsingBlockingPage::~AwSafeBrowsingBlockingPage() {}
- void AwSafeBrowsingBlockingPage::CreatedPostCommitErrorPageNavigation(
- content::NavigationHandle* error_page_navigation_handle) {
- DCHECK(!resource_request_);
- resource_request_ = std::make_unique<AwWebResourceRequest>(
- error_page_navigation_handle->GetURL().spec(),
- error_page_navigation_handle->IsPost() ? "POST" : "GET",
- error_page_navigation_handle->IsInPrimaryMainFrame(),
- error_page_navigation_handle->HasUserGesture(),
- error_page_navigation_handle->GetRequestHeaders());
- resource_request_->is_renderer_initiated =
- error_page_navigation_handle->IsRendererInitiated();
- }
- void AwSafeBrowsingBlockingPage::FinishThreatDetails(
- const base::TimeDelta& delay,
- bool did_proceed,
- int num_visits) {
- // Not all interstitials collect threat details, e.g. when not opted in.
- if (!threat_details_in_progress_)
- return;
- // Finish computing threat details. TriggerManager will decide if it is safe
- // to send the report.
- bool report_sent = AwBrowserProcess::GetInstance()
- ->GetSafeBrowsingTriggerManager()
- ->FinishCollectingThreatDetails(
- safe_browsing::TriggerType::SECURITY_INTERSTITIAL,
- web_contents(), delay, did_proceed, num_visits,
- sb_error_ui()->get_error_display_options());
- if (report_sent) {
- controller()->metrics_helper()->RecordUserInteraction(
- security_interstitials::MetricsHelper::EXTENDED_REPORTING_IS_ENABLED);
- }
- }
- void AwSafeBrowsingBlockingPage::OnInterstitialClosing() {
- if (resource_request_ && !proceeded()) {
- AwContentsClientBridge* client =
- AwContentsClientBridge::FromWebContents(web_contents());
- // With committed interstitials, the navigation to the site is failed before
- // showing the interstitial so we omit notifications to embedders at that
- // time, and manually trigger them here.
- if (client) {
- client->OnReceivedError(*resource_request_,
- safe_browsing::kNetErrorCodeForSafeBrowsing, true,
- false);
- }
- }
- safe_browsing::BaseBlockingPage::OnInterstitialClosing();
- }
- } // namespace android_webview
|