aw_safe_browsing_blocking_page.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright 2017 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. #include "android_webview/browser/safe_browsing/aw_safe_browsing_blocking_page.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "android_webview/browser/aw_browser_context.h"
  8. #include "android_webview/browser/aw_browser_process.h"
  9. #include "android_webview/browser/aw_contents_client_bridge.h"
  10. #include "android_webview/browser/network_service/aw_web_resource_request.h"
  11. #include "android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h"
  12. #include "base/feature_list.h"
  13. #include "base/metrics/histogram_macros.h"
  14. #include "components/prefs/pref_service.h"
  15. #include "components/safe_browsing/content/browser/threat_details.h"
  16. #include "components/safe_browsing/content/browser/triggers/trigger_manager.h"
  17. #include "components/safe_browsing/core/common/features.h"
  18. #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
  19. #include "components/safe_browsing/core/common/utils.h"
  20. #include "components/security_interstitials/content/security_interstitial_controller_client.h"
  21. #include "components/security_interstitials/content/settings_page_helper.h"
  22. #include "components/security_interstitials/content/unsafe_resource_util.h"
  23. #include "components/security_interstitials/core/base_safe_browsing_error_ui.h"
  24. #include "components/security_interstitials/core/safe_browsing_quiet_error_ui.h"
  25. #include "components/security_interstitials/core/unsafe_resource.h"
  26. #include "content/public/browser/navigation_entry.h"
  27. #include "content/public/browser/navigation_handle.h"
  28. #include "content/public/browser/storage_partition.h"
  29. #include "content/public/browser/web_contents.h"
  30. #include "net/base/net_errors.h"
  31. using content::WebContents;
  32. using security_interstitials::BaseSafeBrowsingErrorUI;
  33. using security_interstitials::SafeBrowsingQuietErrorUI;
  34. using security_interstitials::SecurityInterstitialControllerClient;
  35. namespace android_webview {
  36. AwSafeBrowsingBlockingPage::AwSafeBrowsingBlockingPage(
  37. AwSafeBrowsingUIManager* ui_manager,
  38. WebContents* web_contents,
  39. const GURL& main_frame_url,
  40. const UnsafeResourceList& unsafe_resources,
  41. std::unique_ptr<SecurityInterstitialControllerClient> controller_client,
  42. const BaseSafeBrowsingErrorUI::SBErrorDisplayOptions& display_options,
  43. ErrorUiType errorUiType,
  44. std::unique_ptr<AwWebResourceRequest> resource_request)
  45. : BaseBlockingPage(ui_manager,
  46. web_contents,
  47. main_frame_url,
  48. unsafe_resources,
  49. std::move(controller_client),
  50. display_options),
  51. threat_details_in_progress_(false),
  52. resource_request_(std::move(resource_request)) {
  53. if (errorUiType == ErrorUiType::QUIET_SMALL ||
  54. errorUiType == ErrorUiType::QUIET_GIANT) {
  55. set_sb_error_ui(std::make_unique<SafeBrowsingQuietErrorUI>(
  56. unsafe_resources[0].url, main_frame_url,
  57. GetInterstitialReason(unsafe_resources), display_options,
  58. ui_manager->app_locale(), base::Time::NowFromSystemTime(), controller(),
  59. errorUiType == ErrorUiType::QUIET_GIANT));
  60. }
  61. if (unsafe_resources.size() == 1 &&
  62. ShouldReportThreatDetails(unsafe_resources[0].threat_type)) {
  63. AwBrowserContext* aw_browser_context =
  64. AwBrowserContext::FromWebContents(web_contents);
  65. scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
  66. aw_browser_context->GetDefaultStoragePartition()
  67. ->GetURLLoaderFactoryForBrowserProcess();
  68. // TODO(timvolodine): create a proper history service; currently the
  69. // HistoryServiceFactory lives in the chrome/ layer and relies on Profile
  70. // which we don't have in Android WebView (crbug.com/731744).
  71. threat_details_in_progress_ =
  72. AwBrowserProcess::GetInstance()
  73. ->GetSafeBrowsingTriggerManager()
  74. ->StartCollectingThreatDetails(
  75. safe_browsing::TriggerType::SECURITY_INTERSTITIAL, web_contents,
  76. unsafe_resources[0], url_loader_factory,
  77. /*history_service*/ nullptr,
  78. /*referrer_chain_provider*/ nullptr,
  79. sb_error_ui()->get_error_display_options());
  80. }
  81. }
  82. AwSafeBrowsingBlockingPage* AwSafeBrowsingBlockingPage::CreateBlockingPage(
  83. AwSafeBrowsingUIManager* ui_manager,
  84. content::WebContents* web_contents,
  85. const GURL& main_frame_url,
  86. const UnsafeResource& unsafe_resource,
  87. std::unique_ptr<AwWebResourceRequest> resource_request) {
  88. // Log the request destination that triggers the safe browsing blocking page.
  89. UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.BlockingPage.RequestDestination",
  90. unsafe_resource.request_destination);
  91. const UnsafeResourceList unsafe_resources{unsafe_resource};
  92. AwBrowserContext* browser_context =
  93. AwBrowserContext::FromWebContents(web_contents);
  94. PrefService* pref_service = browser_context->GetPrefService();
  95. // TODO(crbug.com/1134678): Set is_enhanced_protection_message_enabled once
  96. // enhanced protection is supported on aw.
  97. BaseSafeBrowsingErrorUI::SBErrorDisplayOptions display_options =
  98. BaseSafeBrowsingErrorUI::SBErrorDisplayOptions(
  99. IsMainPageLoadBlocked(unsafe_resources),
  100. safe_browsing::IsExtendedReportingOptInAllowed(*pref_service),
  101. browser_context->IsOffTheRecord(),
  102. safe_browsing::IsExtendedReportingEnabled(*pref_service),
  103. safe_browsing::IsExtendedReportingPolicyManaged(*pref_service),
  104. safe_browsing::IsEnhancedProtectionEnabled(*pref_service),
  105. pref_service->GetBoolean(::prefs::kSafeBrowsingProceedAnywayDisabled),
  106. false, // should_open_links_in_new_tab
  107. false, // always_show_back_to_safety
  108. false, // is_enhanced_protection_message_enabled
  109. safe_browsing::IsSafeBrowsingPolicyManaged(*pref_service),
  110. "cpn_safe_browsing_wv"); // help_center_article_link
  111. ErrorUiType errorType =
  112. static_cast<ErrorUiType>(ui_manager->GetErrorUiType(web_contents));
  113. // TODO(carlosil): This logic is necessary to support committed and non
  114. // committed interstitials, it can be cleaned up when removing non-committed
  115. // interstitials.
  116. content::NavigationEntry* entry =
  117. GetNavigationEntryForResource(unsafe_resource);
  118. GURL url =
  119. (main_frame_url.is_empty() && entry) ? entry->GetURL() : main_frame_url;
  120. // TODO(crbug.com/1134678): Set settings_page_helper once enhanced protection
  121. // is supported on aw.
  122. return new AwSafeBrowsingBlockingPage(
  123. ui_manager, web_contents, url, unsafe_resources,
  124. CreateControllerClient(web_contents, unsafe_resources, ui_manager,
  125. pref_service, /*settings_page_helper*/ nullptr),
  126. display_options, errorType, std::move(resource_request));
  127. }
  128. AwSafeBrowsingBlockingPage::~AwSafeBrowsingBlockingPage() {}
  129. void AwSafeBrowsingBlockingPage::CreatedPostCommitErrorPageNavigation(
  130. content::NavigationHandle* error_page_navigation_handle) {
  131. DCHECK(!resource_request_);
  132. resource_request_ = std::make_unique<AwWebResourceRequest>(
  133. error_page_navigation_handle->GetURL().spec(),
  134. error_page_navigation_handle->IsPost() ? "POST" : "GET",
  135. error_page_navigation_handle->IsInPrimaryMainFrame(),
  136. error_page_navigation_handle->HasUserGesture(),
  137. error_page_navigation_handle->GetRequestHeaders());
  138. resource_request_->is_renderer_initiated =
  139. error_page_navigation_handle->IsRendererInitiated();
  140. }
  141. void AwSafeBrowsingBlockingPage::FinishThreatDetails(
  142. const base::TimeDelta& delay,
  143. bool did_proceed,
  144. int num_visits) {
  145. // Not all interstitials collect threat details, e.g. when not opted in.
  146. if (!threat_details_in_progress_)
  147. return;
  148. // Finish computing threat details. TriggerManager will decide if it is safe
  149. // to send the report.
  150. bool report_sent = AwBrowserProcess::GetInstance()
  151. ->GetSafeBrowsingTriggerManager()
  152. ->FinishCollectingThreatDetails(
  153. safe_browsing::TriggerType::SECURITY_INTERSTITIAL,
  154. web_contents(), delay, did_proceed, num_visits,
  155. sb_error_ui()->get_error_display_options());
  156. if (report_sent) {
  157. controller()->metrics_helper()->RecordUserInteraction(
  158. security_interstitials::MetricsHelper::EXTENDED_REPORTING_IS_ENABLED);
  159. }
  160. }
  161. void AwSafeBrowsingBlockingPage::OnInterstitialClosing() {
  162. if (resource_request_ && !proceeded()) {
  163. AwContentsClientBridge* client =
  164. AwContentsClientBridge::FromWebContents(web_contents());
  165. // With committed interstitials, the navigation to the site is failed before
  166. // showing the interstitial so we omit notifications to embedders at that
  167. // time, and manually trigger them here.
  168. if (client) {
  169. client->OnReceivedError(*resource_request_,
  170. safe_browsing::kNetErrorCodeForSafeBrowsing, true,
  171. false);
  172. }
  173. }
  174. safe_browsing::BaseBlockingPage::OnInterstitialClosing();
  175. }
  176. } // namespace android_webview