Commit c36cdbc6 authored by Evan Stade's avatar Evan Stade Committed by Commit Bot

[WebLayer] Bring up basic support for SSL error interstitials

* Basic support: a generic SSL interstitial is used for all SSL
  error types

* Interaction: the user can interact with the page (proceed or
  back out). As with WebView, decisions are not saved across
  sessions.

* Minimal impact: much code that we would like to refactor and
  share is instead copied for now to minimize changes outside
  of //weblayer.

This builds on the work of blundell@chromium.org at
https://chromium-review.googlesource.com/c/chromium/src/+/1872091

Testing is facilitated by badssl.com.

Binary-Size: Increase is due to translations and so cannot be avoided.
Change-Id: I68edba70ee8e0ca1078be13d9ab8bc0d96c0321c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1885227Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarMustafa Emre Acer <meacer@chromium.org>
Commit-Queue: Evan Stade <estade@chromium.org>
Cr-Commit-Position: refs/heads/master@{#711516}
parent 73b9f575
...@@ -314,17 +314,33 @@ grit("generate_components_resources") { ...@@ -314,17 +314,33 @@ grit("generate_components_resources") {
] ]
} }
action("concatenate_strings_whitelists") {
script = "//mojo/public/tools/bindings/concatenate-files.py"
inputs = [
"//android_webview/ui/grit_strings_whitelist.txt",
"//weblayer/grit_strings_whitelist.txt",
]
outputs = [
"$target_gen_dir/grit_strings_whitelist.txt",
]
args =
rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir)
}
grit("generate_components_strings") { grit("generate_components_strings") {
source = "../components/components_strings.grd" source = "../components/components_strings.grd"
deps = [
":concatenate_strings_whitelists",
]
# components_strings contains strings from all components. WebView # components_strings contains strings from all components. WebView
# will never display most of them, so we try to limit the included # will never display most of them, so we try to limit the included
# strings. This whitelist trims about 50% more than the compile-based # strings. This whitelist trims about 50% more than the compile-based
# whitelist generated by :system_webview_pak_whitelist. # whitelist generated by :system_webview_pak_whitelist.
whitelist = rebase_path("ui/grit_strings_whitelist.txt", root_build_dir) whitelist =
inputs = [ rebase_path("$target_gen_dir/grit_strings_whitelist.txt", root_build_dir)
"//android_webview/ui/grit_strings_whitelist.txt",
]
grit_flags = [ grit_flags = [
"-w", "-w",
whitelist, whitelist,
......
...@@ -61,4 +61,3 @@ IDS_AUTOFILL_FIELD_LABEL_PREFECTURE ...@@ -61,4 +61,3 @@ IDS_AUTOFILL_FIELD_LABEL_PREFECTURE
IDS_AUTOFILL_FIELD_LABEL_PROVINCE IDS_AUTOFILL_FIELD_LABEL_PROVINCE
IDS_AUTOFILL_FIELD_LABEL_ZIP_CODE IDS_AUTOFILL_FIELD_LABEL_ZIP_CODE
IDS_AUTOFILL_FIELD_LABEL_POSTAL_CODE IDS_AUTOFILL_FIELD_LABEL_POSTAL_CODE
...@@ -53,6 +53,12 @@ jumbo_static_library("weblayer_lib") { ...@@ -53,6 +53,12 @@ jumbo_static_library("weblayer_lib") {
"browser/navigation_impl.h", "browser/navigation_impl.h",
"browser/profile_impl.cc", "browser/profile_impl.cc",
"browser/profile_impl.h", "browser/profile_impl.h",
"browser/ssl_blocking_page.cc",
"browser/ssl_blocking_page.h",
"browser/ssl_error_handler.cc",
"browser/ssl_error_handler.h",
"browser/ssl_host_state_delegate_impl.cc",
"browser/ssl_host_state_delegate_impl.h",
"browser/weblayer_content_browser_overlay_manifest.cc", "browser/weblayer_content_browser_overlay_manifest.cc",
"browser/weblayer_content_browser_overlay_manifest.h", "browser/weblayer_content_browser_overlay_manifest.h",
"browser/webui/web_ui_controller_factory.cc", "browser/webui/web_ui_controller_factory.cc",
...@@ -74,6 +80,10 @@ jumbo_static_library("weblayer_lib") { ...@@ -74,6 +80,10 @@ jumbo_static_library("weblayer_lib") {
"public/navigation_controller.h", "public/navigation_controller.h",
"public/navigation_observer.h", "public/navigation_observer.h",
"public/profile.h", "public/profile.h",
"renderer/content_renderer_client_impl.cc",
"renderer/content_renderer_client_impl.h",
"renderer/ssl_error_helper.cc",
"renderer/ssl_error_helper.h",
"utility/content_utility_client_impl.cc", "utility/content_utility_client_impl.cc",
"utility/content_utility_client_impl.h", "utility/content_utility_client_impl.h",
] ]
...@@ -107,6 +117,10 @@ jumbo_static_library("weblayer_lib") { ...@@ -107,6 +117,10 @@ jumbo_static_library("weblayer_lib") {
"//cc", "//cc",
"//components/crash/content/app", "//components/crash/content/app",
"//components/crash/content/browser", "//components/crash/content/browser",
"//components/resources",
"//components/security_interstitials/content:security_interstitial_page",
"//components/security_interstitials/content/renderer:security_interstitial_page_controller",
"//components/security_interstitials/core",
"//content:resources", "//content:resources",
"//content/app/resources", "//content/app/resources",
"//content/public/app:both", "//content/public/app:both",
...@@ -114,6 +128,7 @@ jumbo_static_library("weblayer_lib") { ...@@ -114,6 +128,7 @@ jumbo_static_library("weblayer_lib") {
"//content/public/child", "//content/public/child",
"//content/public/common", "//content/public/common",
"//content/public/common:service_names", "//content/public/common:service_names",
"//content/public/renderer",
"//content/public/utility", "//content/public/utility",
"//net", "//net",
"//net:net_resources", "//net:net_resources",
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "weblayer/browser/content_browser_client_impl.h" #include "weblayer/browser/content_browser_client_impl.h"
#include "weblayer/common/content_client_impl.h" #include "weblayer/common/content_client_impl.h"
#include "weblayer/common/weblayer_paths.h" #include "weblayer/common/weblayer_paths.h"
#include "weblayer/renderer/content_renderer_client_impl.h"
#include "weblayer/utility/content_utility_client_impl.h" #include "weblayer/utility/content_utility_client_impl.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -246,6 +247,12 @@ ContentMainDelegateImpl::CreateContentBrowserClient() { ...@@ -246,6 +247,12 @@ ContentMainDelegateImpl::CreateContentBrowserClient() {
return browser_client_.get(); return browser_client_.get();
} }
content::ContentRendererClient*
ContentMainDelegateImpl::CreateContentRendererClient() {
renderer_client_ = std::make_unique<ContentRendererClientImpl>();
return renderer_client_.get();
}
content::ContentUtilityClient* content::ContentUtilityClient*
ContentMainDelegateImpl::CreateContentUtilityClient() { ContentMainDelegateImpl::CreateContentUtilityClient() {
utility_client_ = std::make_unique<ContentUtilityClientImpl>(); utility_client_ = std::make_unique<ContentUtilityClientImpl>();
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
namespace weblayer { namespace weblayer {
class ContentClientImpl; class ContentClientImpl;
class ContentBrowserClientImpl; class ContentBrowserClientImpl;
class ContentRendererClientImpl;
class ContentUtilityClientImpl; class ContentUtilityClientImpl;
class ContentMainDelegateImpl : public content::ContentMainDelegate { class ContentMainDelegateImpl : public content::ContentMainDelegate {
...@@ -30,6 +31,7 @@ class ContentMainDelegateImpl : public content::ContentMainDelegate { ...@@ -30,6 +31,7 @@ class ContentMainDelegateImpl : public content::ContentMainDelegate {
const std::string& process_type, const std::string& process_type,
const content::MainFunctionParams& main_function_params) override; const content::MainFunctionParams& main_function_params) override;
content::ContentBrowserClient* CreateContentBrowserClient() override; content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override; content::ContentUtilityClient* CreateContentUtilityClient() override;
private: private:
...@@ -37,6 +39,7 @@ class ContentMainDelegateImpl : public content::ContentMainDelegate { ...@@ -37,6 +39,7 @@ class ContentMainDelegateImpl : public content::ContentMainDelegate {
MainParams params_; MainParams params_;
std::unique_ptr<ContentBrowserClientImpl> browser_client_; std::unique_ptr<ContentBrowserClientImpl> browser_client_;
std::unique_ptr<ContentRendererClientImpl> renderer_client_;
std::unique_ptr<ContentUtilityClientImpl> utility_client_; std::unique_ptr<ContentUtilityClientImpl> utility_client_;
std::unique_ptr<ContentClientImpl> content_client_; std::unique_ptr<ContentClientImpl> content_client_;
......
...@@ -3,6 +3,7 @@ include_rules = [ ...@@ -3,6 +3,7 @@ include_rules = [
"+components/crash/content/browser", "+components/crash/content/browser",
"+components/embedder_support", "+components/embedder_support",
"+components/safe_browsing", "+components/safe_browsing",
"+components/security_interstitials",
"+content/public", "+content/public",
"+mojo/public", "+mojo/public",
"+net", "+net",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "content/public/browser/file_select_listener.h" #include "content/public/browser/file_select_listener.h"
#include "content/public/browser/interstitial_page.h" #include "content/public/browser/interstitial_page.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/browser_controls_state.h" #include "content/public/common/browser_controls_state.h"
...@@ -191,6 +192,19 @@ void BrowserControllerImpl::ExecuteScript( ...@@ -191,6 +192,19 @@ void BrowserControllerImpl::ExecuteScript(
#endif #endif
content::WebContents* BrowserControllerImpl::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
if (params.disposition != WindowOpenDisposition::CURRENT_TAB) {
NOTIMPLEMENTED();
return nullptr;
}
source->GetController().LoadURLWithParams(
content::NavigationController::LoadURLParams(params));
return source;
}
void BrowserControllerImpl::DidNavigateMainFramePostCommit( void BrowserControllerImpl::DidNavigateMainFramePostCommit(
content::WebContents* web_contents) { content::WebContents* web_contents) {
for (auto& observer : observers_) for (auto& observer : observers_)
......
...@@ -81,6 +81,9 @@ class BrowserControllerImpl : public BrowserController, ...@@ -81,6 +81,9 @@ class BrowserControllerImpl : public BrowserController,
#endif #endif
// content::WebContentsDelegate: // content::WebContentsDelegate:
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
void DidNavigateMainFramePostCommit( void DidNavigateMainFramePostCommit(
content::WebContents* web_contents) override; content::WebContents* web_contents) override;
content::ColorChooser* OpenColorChooser( content::ColorChooser* OpenColorChooser(
......
...@@ -12,8 +12,11 @@ ...@@ -12,8 +12,11 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/security_interstitials/content/ssl_cert_reporter.h"
#include "components/security_interstitials/content/ssl_error_navigation_throttle.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/devtools_manager_delegate.h" #include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/network_service_instance.h" #include "content/public/browser/network_service_instance.h"
#include "content/public/common/service_names.mojom.h" #include "content/public/common/service_names.mojom.h"
#include "content/public/common/user_agent.h" #include "content/public/common/user_agent.h"
...@@ -27,6 +30,7 @@ ...@@ -27,6 +30,7 @@
#include "url/origin.h" #include "url/origin.h"
#include "weblayer/browser/browser_controller_impl.h" #include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/browser_main_parts_impl.h" #include "weblayer/browser/browser_main_parts_impl.h"
#include "weblayer/browser/ssl_error_handler.h"
#include "weblayer/browser/weblayer_content_browser_overlay_manifest.h" #include "weblayer/browser/weblayer_content_browser_overlay_manifest.h"
#include "weblayer/common/features.h" #include "weblayer/common/features.h"
#include "weblayer/public/fullscreen_delegate.h" #include "weblayer/public/fullscreen_delegate.h"
...@@ -60,6 +64,16 @@ bool IsSafebrowsingSupported() { ...@@ -60,6 +64,16 @@ bool IsSafebrowsingSupported() {
return false; return false;
} }
bool IsInHostedApp(content::WebContents* web_contents) {
return false;
}
class SSLCertReporterImpl : public SSLCertReporter {
public:
void ReportInvalidCertificateChain(
const std::string& serialized_report) override {}
};
} // namespace } // namespace
namespace weblayer { namespace weblayer {
...@@ -189,6 +203,16 @@ ContentBrowserClientImpl::CreateURLLoaderThrottles( ...@@ -189,6 +203,16 @@ ContentBrowserClientImpl::CreateURLLoaderThrottles(
return result; return result;
} }
std::vector<std::unique_ptr<content::NavigationThrottle>>
ContentBrowserClientImpl::CreateThrottlesForNavigation(
content::NavigationHandle* handle) {
std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
throttles.push_back(std::make_unique<SSLErrorNavigationThrottle>(
handle, std::make_unique<SSLCertReporterImpl>(),
base::Bind(&HandleSSLError), base::Bind(&IsInHostedApp)));
return throttles;
}
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_LINUX) || defined(OS_ANDROID)
void ContentBrowserClientImpl::GetAdditionalMappedFilesForChildProcess( void ContentBrowserClientImpl::GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line, const base::CommandLine& command_line,
......
...@@ -51,6 +51,8 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient { ...@@ -51,6 +51,8 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient {
const base::RepeatingCallback<content::WebContents*()>& wc_getter, const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data, content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) override; int frame_tree_node_id) override;
std::vector<std::unique_ptr<content::NavigationThrottle>>
CreateThrottlesForNavigation(content::NavigationHandle* handle) override;
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_LINUX) || defined(OS_ANDROID)
void GetAdditionalMappedFilesForChildProcess( void GetAdditionalMappedFilesForChildProcess(
......
...@@ -4,14 +4,15 @@ ...@@ -4,14 +4,15 @@
#include "weblayer/browser/profile_impl.h" #include "weblayer/browser/profile_impl.h"
#include "base/callback.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_manager_delegate.h" #include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/resource_context.h" #include "content/public/browser/resource_context.h"
#include "weblayer/browser/browser_controller_impl.h" #include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/ssl_host_state_delegate_impl.h"
#include "weblayer/public/download_delegate.h" #include "weblayer/public/download_delegate.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
...@@ -120,7 +121,7 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext { ...@@ -120,7 +121,7 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext {
} }
content::SSLHostStateDelegate* GetSSLHostStateDelegate() override { content::SSLHostStateDelegate* GetSSLHostStateDelegate() override {
return nullptr; return &ssl_host_state_delegate_;
} }
content::PermissionControllerDelegate* GetPermissionControllerDelegate() content::PermissionControllerDelegate* GetPermissionControllerDelegate()
...@@ -154,6 +155,7 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext { ...@@ -154,6 +155,7 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext {
base::FilePath path_; base::FilePath path_;
std::unique_ptr<ResourceContextImpl> resource_context_; std::unique_ptr<ResourceContextImpl> resource_context_;
DownloadManagerDelegateImpl download_delegate_; DownloadManagerDelegateImpl download_delegate_;
SSLHostStateDelegateImpl ssl_host_state_delegate_;
DISALLOW_COPY_AND_ASSIGN(BrowserContextImpl); DISALLOW_COPY_AND_ASSIGN(BrowserContextImpl);
}; };
......
// Copyright 2019 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 "weblayer/browser/ssl_blocking_page.h"
#include <memory>
#include <utility>
#include "components/security_interstitials/content/security_interstitial_controller_client.h"
#include "components/security_interstitials/core/metrics_helper.h"
#include "components/security_interstitials/core/ssl_error_options_mask.h"
#include "components/security_interstitials/core/ssl_error_ui.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
#include "net/base/net_errors.h"
namespace weblayer {
namespace {
// A stripped-down version of the class by the same name in
// //chrome/browser/ssl, which provides basic functionality for interacting with
// the SSL interstitial.
class SSLErrorControllerClient
: public security_interstitials::SecurityInterstitialControllerClient {
public:
SSLErrorControllerClient(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper)
: security_interstitials::SecurityInterstitialControllerClient(
web_contents,
std::move(metrics_helper),
nullptr /*prefs*/,
"en_US",
GURL("chrome://newtab")),
cert_error_(cert_error),
ssl_info_(ssl_info),
request_url_(request_url) {}
~SSLErrorControllerClient() override = default;
void GoBack() override {
SecurityInterstitialControllerClient::GoBackAfterNavigationCommitted();
}
void Proceed() override {
web_contents_->GetBrowserContext()->GetSSLHostStateDelegate()->AllowCert(
request_url_.host(), *ssl_info_.cert.get(), cert_error_);
Reload();
}
void OpenUrlInNewForegroundTab(const GURL& url) override {
// For now WebLayer doesn't support multiple tabs, so just open the Learn
// More link in the current tab.
OpenUrlInCurrentTab(url);
}
private:
const int cert_error_;
const net::SSLInfo ssl_info_;
const GURL request_url_;
DISALLOW_COPY_AND_ASSIGN(SSLErrorControllerClient);
};
} // namespace
// static
const content::InterstitialPageDelegate::TypeID
SSLBlockingPage::kTypeForTesting = &SSLBlockingPage::kTypeForTesting;
// static
SSLBlockingPage* SSLBlockingPage::Create(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
int options_mask,
const base::Time& time_triggered,
const base::Callback<void(content::CertificateRequestResultType)>&
callback) {
bool overridable = IsOverridable(options_mask);
security_interstitials::MetricsHelper::ReportDetails report_details;
report_details.metric_prefix =
overridable ? "ssl_overridable" : "ssl_nonoverridable";
auto metrics_helper = std::make_unique<security_interstitials::MetricsHelper>(
request_url, report_details, /*history_service=*/nullptr);
return new SSLBlockingPage(web_contents, cert_error, ssl_info, request_url,
options_mask, time_triggered, overridable,
std::move(metrics_helper), callback);
}
bool SSLBlockingPage::ShouldCreateNewNavigation() const {
return true;
}
content::InterstitialPageDelegate::TypeID SSLBlockingPage::GetTypeForTesting() {
return SSLBlockingPage::kTypeForTesting;
}
SSLBlockingPage::~SSLBlockingPage() = default;
void SSLBlockingPage::PopulateInterstitialStrings(
base::DictionaryValue* load_time_data) {
ssl_error_ui_->PopulateStringsForHTML(load_time_data);
}
// Note that we always create a navigation entry with SSL errors.
// No error happening loading a sub-resource triggers an interstitial so far.
SSLBlockingPage::SSLBlockingPage(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
int options_mask,
const base::Time& time_triggered,
bool overridable,
std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper,
const base::Callback<void(content::CertificateRequestResultType)>& callback)
: security_interstitials::SecurityInterstitialPage(
web_contents,
request_url,
std::make_unique<SSLErrorControllerClient>(
web_contents,
cert_error,
ssl_info,
request_url,
std::move(metrics_helper))),
ssl_info_(ssl_info),
ssl_error_ui_(std::make_unique<security_interstitials::SSLErrorUI>(
request_url,
cert_error,
ssl_info,
options_mask,
time_triggered,
/*support_url=*/GURL(),
controller())) {
DCHECK(callback.is_null());
}
void SSLBlockingPage::OverrideEntry(content::NavigationEntry* entry) {
entry->GetSSL() = content::SSLStatus(ssl_info_);
}
// This handles the commands sent from the interstitial JavaScript.
void SSLBlockingPage::CommandReceived(const std::string& command) {
// content::WaitForRenderFrameReady sends this message when the page
// load completes. Ignore it.
if (command == "\"pageLoadComplete\"")
return;
int cmd = 0;
bool retval = base::StringToInt(command, &cmd);
DCHECK(retval);
ssl_error_ui_->HandleCommand(
static_cast<security_interstitials::SecurityInterstitialCommand>(cmd));
}
void SSLBlockingPage::OnInterstitialClosing() {
// TODO(blundell): Does this need to track metrics analogously to //chrome's
// SSLBlockingPageBase::OnInterstitialClosing()?
}
// static
bool SSLBlockingPage::IsOverridable(int options_mask) {
const bool is_overridable =
(options_mask &
security_interstitials::SSLErrorOptionsMask::SOFT_OVERRIDE_ENABLED) &&
!(options_mask &
security_interstitials::SSLErrorOptionsMask::STRICT_ENFORCEMENT) &&
!(options_mask &
security_interstitials::SSLErrorOptionsMask::HARD_OVERRIDE_DISABLED);
return is_overridable;
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_BROWSER_SSL_BLOCKING_PAGE_H_
#define WEBLAYER_BROWSER_SSL_BLOCKING_PAGE_H_
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "components/security_interstitials/content/security_interstitial_page.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "net/ssl/ssl_info.h"
#include "url/gurl.h"
namespace security_interstitials {
class MetricsHelper;
class SSLErrorUI;
} // namespace security_interstitials
namespace weblayer {
// A stripped-down version of the class of the same name in
// //chrome/browser/ssl. TODO(estade,blundell): componentize and share instead
// of copying.
class SSLBlockingPage
: public security_interstitials::SecurityInterstitialPage {
public:
// Interstitial type, used in tests.
static const InterstitialPageDelegate::TypeID kTypeForTesting;
~SSLBlockingPage() override;
// Creates an SSL blocking page. If the blocking page isn't shown, the caller
// is responsible for cleaning up the blocking page, otherwise the
// interstitial takes ownership when shown. |options_mask| must be a bitwise
// mask of SSLErrorUI::SSLErrorOptionsMask values.
// This is static because the constructor uses expensive to compute parameters
// more than once (e.g. overrideable).
static SSLBlockingPage* Create(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
int options_mask,
const base::Time& time_triggered,
const base::Callback<void(content::CertificateRequestResultType)>&
callback);
// InterstitialPageDelegate:
InterstitialPageDelegate::TypeID GetTypeForTesting() override;
// Returns true if |options_mask| refers to a soft-overridable SSL error and
// if SSL error overriding is allowed by policy.
static bool IsOverridable(int options_mask);
// InterstitialPageDelegate.
void CommandReceived(const std::string& command) override;
void OverrideEntry(content::NavigationEntry* entry) override;
void OnInterstitialClosing() override;
// SecurityInterstitialPage:
bool ShouldCreateNewNavigation() const override;
void PopulateInterstitialStrings(
base::DictionaryValue* load_time_data) override;
protected:
SSLBlockingPage(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
int options_mask,
const base::Time& time_triggered,
bool overrideable,
std::unique_ptr<security_interstitials::MetricsHelper> metrics_helper,
const base::Callback<void(content::CertificateRequestResultType)>&
callback);
private:
base::Callback<void(content::CertificateRequestResultType)> callback_;
const net::SSLInfo ssl_info_;
const std::unique_ptr<security_interstitials::SSLErrorUI> ssl_error_ui_;
DISALLOW_COPY_AND_ASSIGN(SSLBlockingPage);
};
} // namespace weblayer
#endif // WEBLAYER_BROWSER_SSL_BLOCKING_PAGE_H_
// Copyright 2019 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 "weblayer/browser/ssl_error_handler.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/security_interstitials/content/ssl_cert_reporter.h"
#include "components/security_interstitials/content/ssl_error_navigation_throttle.h"
#include "components/security_interstitials/core/ssl_error_options_mask.h"
#include "components/security_interstitials/core/ssl_error_ui.h"
#include "weblayer/browser/ssl_blocking_page.h"
#include "weblayer/browser/weblayer_content_browser_overlay_manifest.h"
namespace {
// Constructs and shows an SSL interstitial. Adapted from //chrome's
// SSLErrorHandlerDelegateImpl::ShowSSLInterstitial().
void ShowSSLInterstitial(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
const base::Callback<void(content::CertificateRequestResultType)>&
decision_callback,
base::OnceCallback<
void(std::unique_ptr<security_interstitials::SecurityInterstitialPage>)>
blocking_page_ready_callback,
int options_mask) {
auto* interstitial_page = weblayer::SSLBlockingPage::Create(
web_contents, cert_error, ssl_info, request_url, options_mask,
base::Time::NowFromSystemTime(), decision_callback);
// Note: |blocking_page_ready_callback| must be posted due to
// HandleSSLError()'s guarantee that it will not invoke this callback
// synchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(blocking_page_ready_callback),
base::WrapUnique(interstitial_page)));
}
} // namespace
namespace weblayer {
void HandleSSLError(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
const base::Callback<void(content::CertificateRequestResultType)>&
decision_callback,
base::OnceCallback<
void(std::unique_ptr<security_interstitials::SecurityInterstitialPage>)>
blocking_page_ready_callback) {
// NOTE: In Chrome hard overrides can be disabled for the Profile by setting
// the kSSLErrorOverrideAllowed preference (which defaults to true) to false.
// However, in WebLayer there is currently no way for the user to set this
// preference.
bool hard_override_disabled = false;
int options_mask = security_interstitials::CalculateSSLErrorOptionsMask(
cert_error, hard_override_disabled, ssl_info.is_fatal_cert_error);
// Handle all errors by showing SSL interstitials. If this needs to get more
// refined in the short-term, can adapt logic from
// SSLErrorHandler::StartHandlingError() as needed (in the long-term, WebLayer
// will most likely share a componentized version of //chrome's
// SSLErrorHandler).
ShowSSLInterstitial(web_contents, cert_error, ssl_info, request_url,
std::move(ssl_cert_reporter),
std::move(decision_callback),
std::move(blocking_page_ready_callback), options_mask);
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_BROWSER_SSL_ERROR_HANDLER_H_
#define WEBLAYER_BROWSER_SSL_ERROR_HANDLER_H_
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "components/security_interstitials/content/security_interstitial_page.h"
#include "content/public/browser/certificate_request_result_type.h"
#include "net/ssl/ssl_info.h"
#include "url/gurl.h"
class SSLCertReporter;
namespace weblayer {
using BlockingPageReadyCallback = base::OnceCallback<void(
std::unique_ptr<security_interstitials::SecurityInterstitialPage>)>;
// This code is responsible for deciding what type of interstitial to display
// for an SSL validation error and actually displaying it. It is a greatly
// simplified version of //chrome's SSLErrorHandler; in the long run that class
// should be componentized and WebLayer should replace its usage of this
// simplified version with usage of that class.
// Entrypoint for handling SSL errors. All parameters except
// |blocking_page_ready_callback| are the same as SSLBlockingPage constructor.
// This function creates an interstitial and passes it to
// |blocking_page_ready_callback|.
// |blocking_page_ready_callback| is guaranteed not to be called
// synchronously.
void HandleSSLError(
content::WebContents* web_contents,
int cert_error,
const net::SSLInfo& ssl_info,
const GURL& request_url,
std::unique_ptr<SSLCertReporter> ssl_cert_reporter,
const base::Callback<void(content::CertificateRequestResultType)>&
decision_callback,
BlockingPageReadyCallback blocking_page_ready_callback);
} // namespace weblayer
#endif // WEBLAYER_BROWSER_SSL_ERROR_HANDLER_H_
// Copyright 2019 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 "weblayer/browser/ssl_host_state_delegate_impl.h"
#include "base/callback.h"
#include "net/base/hash_value.h"
using content::SSLHostStateDelegate;
namespace weblayer {
namespace internal {
CertPolicy::CertPolicy() = default;
CertPolicy::~CertPolicy() = default;
// For an allowance, we consider a given |cert| to be a match to a saved
// allowed cert if the |error| is an exact match to or subset of the errors
// in the saved CertStatus.
bool CertPolicy::Check(const net::X509Certificate& cert, int error) const {
net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256();
auto allowed_iter = allowed_.find(fingerprint);
return ((allowed_iter != allowed_.end()) && (allowed_iter->second & error) &&
((allowed_iter->second & error) == error));
}
void CertPolicy::Allow(const net::X509Certificate& cert, int error) {
// If this same cert had already been saved with a different error status,
// this will replace it with the new error status.
net::SHA256HashValue fingerprint = cert.CalculateChainFingerprint256();
allowed_[fingerprint] = error;
}
} // namespace internal
SSLHostStateDelegateImpl::SSLHostStateDelegateImpl() = default;
SSLHostStateDelegateImpl::~SSLHostStateDelegateImpl() = default;
void SSLHostStateDelegateImpl::HostRanInsecureContent(
const std::string& host,
int child_id,
InsecureContentType content_type) {
// Intentional no-op.
}
bool SSLHostStateDelegateImpl::DidHostRunInsecureContent(
const std::string& host,
int child_id,
InsecureContentType content_type) {
// Intentional no-op.
return false;
}
void SSLHostStateDelegateImpl::AllowCert(const std::string& host,
const net::X509Certificate& cert,
int error) {
cert_policy_for_host_[host].Allow(cert, error);
}
void SSLHostStateDelegateImpl::Clear(
const base::Callback<bool(const std::string&)>& host_filter) {
if (host_filter.is_null()) {
cert_policy_for_host_.clear();
return;
}
for (auto it = cert_policy_for_host_.begin();
it != cert_policy_for_host_.end();) {
auto next_it = std::next(it);
if (host_filter.Run(it->first))
cert_policy_for_host_.erase(it);
it = next_it;
}
}
SSLHostStateDelegate::CertJudgment SSLHostStateDelegateImpl::QueryPolicy(
const std::string& host,
const net::X509Certificate& cert,
int error) {
return cert_policy_for_host_[host].Check(cert, error)
? SSLHostStateDelegate::ALLOWED
: SSLHostStateDelegate::DENIED;
}
void SSLHostStateDelegateImpl::RevokeUserAllowExceptions(
const std::string& host) {
cert_policy_for_host_.erase(host);
}
bool SSLHostStateDelegateImpl::HasAllowException(const std::string& host) {
auto policy_iterator = cert_policy_for_host_.find(host);
return policy_iterator != cert_policy_for_host_.end() &&
policy_iterator->second.HasAllowException();
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_BROWSER_SSL_HOST_STATE_DELEGATE_IMPL_H_
#define WEBLAYER_BROWSER_SSL_HOST_STATE_DELEGATE_IMPL_H_
#include <map>
#include <string>
#include "base/macros.h"
#include "content/public/browser/ssl_host_state_delegate.h"
#include "net/base/hash_value.h"
#include "net/cert/x509_certificate.h"
namespace weblayer {
namespace internal {
// This class maintains the policy for storing actions on certificate errors.
class CertPolicy {
public:
CertPolicy();
~CertPolicy();
// Returns true if the user has decided to proceed through the ssl error
// before. For a certificate to be allowed, it must not have any
// *additional* errors from when it was allowed.
bool Check(const net::X509Certificate& cert, int error) const;
// Causes the policy to allow this certificate for a given |error|. And
// remember the user's choice.
void Allow(const net::X509Certificate& cert, int error);
// Returns true if and only if there exists a user allow exception for some
// certificate.
bool HasAllowException() const { return allowed_.size() > 0; }
private:
// The set of fingerprints of allowed certificates.
std::map<net::SHA256HashValue, int> allowed_;
};
} // namespace internal
// This class is a copy of AwSSLHostStateDelegate. It saves cert decisions in
// memory, and doesn't perpetuate across application restarts.
class SSLHostStateDelegateImpl : public content::SSLHostStateDelegate {
public:
SSLHostStateDelegateImpl();
~SSLHostStateDelegateImpl() override;
// Records that |cert| is permitted to be used for |host| in the future, for
// a specified |error| type.
void AllowCert(const std::string& host,
const net::X509Certificate& cert,
int error) override;
void Clear(
const base::Callback<bool(const std::string&)>& host_filter) override;
// content::SSLHostStateDelegate:
content::SSLHostStateDelegate::CertJudgment QueryPolicy(
const std::string& host,
const net::X509Certificate& cert,
int error) override;
void HostRanInsecureContent(const std::string& host,
int child_id,
InsecureContentType content_type) override;
bool DidHostRunInsecureContent(const std::string& host,
int child_id,
InsecureContentType content_type) override;
void RevokeUserAllowExceptions(const std::string& host) override;
bool HasAllowException(const std::string& host) override;
private:
// Certificate policies for each host.
std::map<std::string, internal::CertPolicy> cert_policy_for_host_;
DISALLOW_COPY_AND_ASSIGN(SSLHostStateDelegateImpl);
};
} // namespace weblayer
#endif // WEBLAYER_BROWSER_SSL_HOST_STATE_DELEGATE_IMPL_H_
IDS_SSL_OPEN_DETAILS_BUTTON
IDS_SSL_CLOSE_DETAILS_BUTTON
IDS_SSL_OVERRIDABLE_SAFETY_BUTTON
IDS_SSL_OVERRIDABLE_PROCEED_PARAGRAPH
IDS_SSL_V2_TITLE
IDS_SSL_V2_HEADING
IDS_SSL_V2_PRIMARY_PARAGRAPH
IDS_SSL_V2_RECURRENT_ERROR_PARAGRAPH
IDS_CERT_ERROR_COMMON_NAME_INVALID_DETAILS
IDS_CERT_ERROR_COMMON_NAME_INVALID_DESCRIPTION
IDS_CERT_ERROR_EXPIRED_DETAILS
IDS_CERT_ERROR_EXPIRED_DESCRIPTION
IDS_CERT_ERROR_NOT_YET_VALID_DETAILS
IDS_CERT_ERROR_NOT_YET_VALID_DESCRIPTION
IDS_CERT_ERROR_NOT_VALID_AT_THIS_TIME_DETAILS
IDS_CERT_ERROR_NOT_VALID_AT_THIS_TIME_DESCRIPTION
IDS_CERT_ERROR_AUTHORITY_INVALID_DETAILS
IDS_CERT_ERROR_AUTHORITY_INVALID_DESCRIPTION
IDS_CERT_ERROR_CONTAINS_ERRORS_DETAILS
IDS_CERT_ERROR_CONTAINS_ERRORS_DESCRIPTION
IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DETAILS
IDS_CERT_ERROR_NO_REVOCATION_MECHANISM_DESCRIPTION
IDS_CERT_ERROR_REVOKED_CERT_DETAILS
IDS_CERT_ERROR_REVOKED_CERT_DESCRIPTION
IDS_CERT_ERROR_INVALID_CERT_DETAILS
IDS_CERT_ERROR_INVALID_CERT_DESCRIPTION
IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DETAILS
IDS_CERT_ERROR_WEAK_SIGNATURE_ALGORITHM_DESCRIPTION
IDS_CERT_ERROR_WEAK_KEY_DETAILS
IDS_CERT_ERROR_WEAK_KEY_DESCRIPTION
IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DETAILS
IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION
IDS_CERT_ERROR_VALIDITY_TOO_LONG_DETAILS
IDS_CERT_ERROR_VALIDITY_TOO_LONG_DESCRIPTION
IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DETAILS
IDS_CERT_ERROR_SUMMARY_PINNING_FAILURE_DESCRIPTION
IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DETAILS
IDS_CERT_ERROR_UNABLE_TO_CHECK_REVOCATION_DESCRIPTION
IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DETAILS
IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DESCRIPTION
IDS_CERT_ERROR_UNKNOWN_ERROR_DETAILS
IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION
IDS_CERT_ERROR_NO_SUBJECT_ALTERNATIVE_NAMES_DETAILS
include_rules = [
"+components/security_interstitials/content/renderer",
"+components/security_interstitials/core/common",
"+content/public/renderer",
"+third_party/blink/public/common",
]
// Copyright 2019 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 "weblayer/renderer/content_renderer_client_impl.h"
#include "weblayer/renderer/ssl_error_helper.h"
namespace weblayer {
ContentRendererClientImpl::ContentRendererClientImpl() = default;
ContentRendererClientImpl::~ContentRendererClientImpl() = default;
void ContentRendererClientImpl::RenderFrameCreated(
content::RenderFrame* render_frame) {
SSLErrorHelper::Create(render_frame);
}
void ContentRendererClientImpl::PrepareErrorPage(
content::RenderFrame* render_frame,
const blink::WebURLError& error,
const std::string& http_method,
std::string* error_html) {
auto* ssl_helper = SSLErrorHelper::GetForFrame(render_frame);
if (ssl_helper)
ssl_helper->PrepareErrorPage();
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_RENDERER_CONTENT_RENDERER_CLIENT_IMPL_H_
#define WEBLAYER_RENDERER_CONTENT_RENDERER_CLIENT_IMPL_H_
#include "base/macros.h"
#include "content/public/renderer/content_renderer_client.h"
namespace weblayer {
class ContentRendererClientImpl : public content::ContentRendererClient {
public:
ContentRendererClientImpl();
~ContentRendererClientImpl() override;
// content::ContentRendererClient:
void RenderFrameCreated(content::RenderFrame* render_frame) override;
void PrepareErrorPage(content::RenderFrame* render_frame,
const blink::WebURLError& error,
const std::string& http_method,
std::string* error_html) override;
private:
DISALLOW_COPY_AND_ASSIGN(ContentRendererClientImpl);
};
} // namespace weblayer
#endif // WEBLAYER_RENDERER_CONTENT_RENDERER_CLIENT_IMPL_H_
// Copyright 2019 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 "weblayer/renderer/ssl_error_helper.h"
#include "components/security_interstitials/core/common/mojom/interstitial_commands.mojom.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace weblayer {
// static
void SSLErrorHelper::Create(content::RenderFrame* render_frame) {
if (render_frame->IsMainFrame())
new SSLErrorHelper(render_frame);
}
// static
SSLErrorHelper* SSLErrorHelper::GetForFrame(
content::RenderFrame* render_frame) {
return render_frame->IsMainFrame() ? Get(render_frame) : nullptr;
}
void SSLErrorHelper::PrepareErrorPage() {
next_load_is_error_ = true;
}
void SSLErrorHelper::DidCommitProvisionalLoad(bool is_same_document_navigation,
ui::PageTransition transition) {
if (is_same_document_navigation)
return;
weak_factory_.InvalidateWeakPtrs();
this_load_is_error_ = next_load_is_error_;
next_load_is_error_ = false;
}
void SSLErrorHelper::DidFinishLoad() {
if (this_load_is_error_) {
security_interstitials::SecurityInterstitialPageController::Install(
render_frame(), weak_factory_.GetWeakPtr());
}
}
void SSLErrorHelper::OnDestruct() {
delete this;
}
void SSLErrorHelper::SendCommand(
security_interstitials::SecurityInterstitialCommand command) {
mojo::AssociatedRemote<security_interstitials::mojom::InterstitialCommands>
interface;
render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(&interface);
switch (command) {
case security_interstitials::CMD_DONT_PROCEED:
interface->DontProceed();
break;
case security_interstitials::CMD_PROCEED:
interface->Proceed();
break;
case security_interstitials::CMD_SHOW_MORE_SECTION:
interface->ShowMoreSection();
break;
case security_interstitials::CMD_OPEN_HELP_CENTER:
interface->OpenHelpCenter();
break;
case security_interstitials::CMD_OPEN_DIAGNOSTIC:
case security_interstitials::CMD_RELOAD:
case security_interstitials::CMD_OPEN_DATE_SETTINGS:
case security_interstitials::CMD_OPEN_LOGIN:
case security_interstitials::CMD_DO_REPORT:
case security_interstitials::CMD_DONT_REPORT:
case security_interstitials::CMD_OPEN_REPORTING_PRIVACY:
case security_interstitials::CMD_OPEN_WHITEPAPER:
case security_interstitials::CMD_REPORT_PHISHING_ERROR:
// Commands not used by the generic SSL error page.
NOTREACHED();
break;
case security_interstitials::CMD_ERROR:
case security_interstitials::CMD_TEXT_FOUND:
case security_interstitials::CMD_TEXT_NOT_FOUND:
// Commands for testing.
NOTREACHED();
break;
}
}
SSLErrorHelper::SSLErrorHelper(content::RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
RenderFrameObserverTracker<SSLErrorHelper>(render_frame) {}
SSLErrorHelper::~SSLErrorHelper() = default;
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_RENDERER_SSL_ERROR_HELPER_H_
#define WEBLAYER_RENDERER_SSL_ERROR_HELPER_H_
#include "base/memory/weak_ptr.h"
#include "components/security_interstitials/content/renderer/security_interstitial_page_controller.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_observer_tracker.h"
namespace weblayer {
// A class that helps present SSL interstitials by enabling security
// interstitial javascript in WebContents that have navigation errors. This is a
// stripped down version of Chrome's NetErrorHelper.
class SSLErrorHelper
: public content::RenderFrameObserver,
public content::RenderFrameObserverTracker<SSLErrorHelper>,
public security_interstitials::SecurityInterstitialPageController::
Delegate {
public:
// Creates an SSLErrorHelper which will observe and tie its lifetime to
// |render_frame|, if it's a main frame. SSLErrorHelpers will not be created
// for sub frames.
static void Create(content::RenderFrame* render_frame);
// Returns the SSLErrorHelper for the frame, if it exists.
static SSLErrorHelper* GetForFrame(content::RenderFrame* render_frame);
// Called when the current navigation results in an error.
void PrepareErrorPage();
// content::RenderFrameObserver:
void DidCommitProvisionalLoad(bool is_same_document_navigation,
ui::PageTransition transition) override;
void DidFinishLoad() override;
void OnDestruct() override;
// security_interstitials::SecurityInterstitialPageController::Delegate:
void SendCommand(
security_interstitials::SecurityInterstitialCommand command) override;
private:
explicit SSLErrorHelper(content::RenderFrame* render_frame);
~SSLErrorHelper() override;
bool next_load_is_error_ = false;
bool this_load_is_error_ = false;
base::WeakPtrFactory<SSLErrorHelper> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SSLErrorHelper);
};
} // namespace weblayer
#endif // WEBLAYER_RENDERER_SSL_ERROR_HELPER_H_
...@@ -173,6 +173,9 @@ repack("support_pak") { ...@@ -173,6 +173,9 @@ repack("support_pak") {
testonly = true testonly = true
sources = [ sources = [
"$root_gen_dir/components/components_resources.pak",
"$root_gen_dir/components/components_resources_100_percent.pak",
"$root_gen_dir/components/strings/components_strings_en-US.pak",
"$root_gen_dir/content/app/resources/content_resources_100_percent.pak", "$root_gen_dir/content/app/resources/content_resources_100_percent.pak",
"$root_gen_dir/content/browser/tracing/tracing_resources.pak", "$root_gen_dir/content/browser/tracing/tracing_resources.pak",
"$root_gen_dir/content/content_resources.pak", "$root_gen_dir/content/content_resources.pak",
...@@ -189,6 +192,8 @@ repack("support_pak") { ...@@ -189,6 +192,8 @@ repack("support_pak") {
] ]
deps = [ deps = [
"//components/resources",
"//components/strings",
"//content:resources", "//content:resources",
"//content/app/resources", "//content/app/resources",
"//content/browser/tracing:resources", "//content/browser/tracing:resources",
......
...@@ -74,8 +74,11 @@ test("weblayer_browsertests") { ...@@ -74,8 +74,11 @@ test("weblayer_browsertests") {
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
deps = [ deps = [
"//base",
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//components/security_interstitials/content:security_interstitial_page",
"//content/public/browser",
"//content/test:test_support", "//content/test:test_support",
"//net:test_support", "//net:test_support",
"//testing/gtest", "//testing/gtest",
...@@ -86,6 +89,8 @@ test("weblayer_browsertests") { ...@@ -86,6 +89,8 @@ test("weblayer_browsertests") {
sources = [ sources = [
"../browser/webui/webui_browsertest.cc", "../browser/webui/webui_browsertest.cc",
"browsertests_main.cc", "browsertests_main.cc",
"interstitial_utils.cc",
"interstitial_utils.h",
"ssl_browsertest.cc", "ssl_browsertest.cc",
"test_launcher_delegate_impl.cc", "test_launcher_delegate_impl.cc",
"test_launcher_delegate_impl.h", "test_launcher_delegate_impl.h",
......
include_rules = [ include_rules = [
"+components/security_interstitials",
"+content/public/common", "+content/public/common",
"+content/public/test", "+content/public/test",
"+net/test", "+net/test",
......
// Copyright 2019 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 "weblayer/test/interstitial_utils.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
#include "weblayer/browser/browser_controller_impl.h"
#include "weblayer/browser/ssl_blocking_page.h"
namespace weblayer {
namespace {
// Returns the security interstitial currently showing in |browser_controller|,
// or null if there is no such interstitial.
security_interstitials::SecurityInterstitialPage*
GetCurrentlyShowingInterstitial(BrowserController* browser_controller) {
BrowserControllerImpl* browser_controller_impl =
static_cast<BrowserControllerImpl*>(browser_controller);
security_interstitials::SecurityInterstitialTabHelper* helper =
security_interstitials::SecurityInterstitialTabHelper::FromWebContents(
browser_controller_impl->web_contents());
return helper
? helper
->GetBlockingPageForCurrentlyCommittedNavigationForTesting()
: nullptr;
}
} // namespace
bool IsShowingSecurityInterstitial(BrowserController* browser_controller) {
return GetCurrentlyShowingInterstitial(browser_controller) != nullptr;
}
bool IsShowingSSLInterstitial(BrowserController* browser_controller) {
auto* blocking_page = GetCurrentlyShowingInterstitial(browser_controller);
if (!blocking_page)
return false;
return blocking_page->GetTypeForTesting() == SSLBlockingPage::kTypeForTesting;
}
} // namespace weblayer
// Copyright 2019 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.
#ifndef WEBLAYER_TEST_INTERSTITIAL_UTILS_H_
#define WEBLAYER_TEST_INTERSTITIAL_UTILS_H_
namespace weblayer {
class BrowserController;
// Contains utilities for aiding in testing an embedder's integration of
// WebLayer's interstitial functionality.
// Returns true iff a security interstitial is currently displaying in
// |browser_controller|.
bool IsShowingSecurityInterstitial(BrowserController* browser_controller);
// Returns true iff an SSL error-related interstitial is currently displaying in
// |browser_controller|.
bool IsShowingSSLInterstitial(BrowserController* browser_controller);
} // namespace weblayer
#endif // WEBLAYER_TEST_INTERSTITIAL_UTILS_H_
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/embedded_test_server.h"
#include "weblayer/shell/browser/shell.h"
#include "weblayer/test/interstitial_utils.h"
#include "weblayer/test/weblayer_browser_test_utils.h" #include "weblayer/test/weblayer_browser_test_utils.h"
namespace weblayer { namespace weblayer {
IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, Https) { IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, SSLErrorMismatchedCertificate) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.AddDefaultHandlers( https_server.AddDefaultHandlers(
base::FilePath(FILE_PATH_LITERAL("weblayer/test/data"))); base::FilePath(FILE_PATH_LITERAL("weblayer/test/data")));
...@@ -30,6 +32,7 @@ IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, Https) { ...@@ -30,6 +32,7 @@ IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, Https) {
ASSERT_EQ("127.0.0.1", initial_url.host()); ASSERT_EQ("127.0.0.1", initial_url.host());
NavigateAndWaitForCompletion(initial_url, shell()); NavigateAndWaitForCompletion(initial_url, shell());
EXPECT_FALSE(IsShowingSecurityInterstitial(shell()->browser_controller()));
// Now do a navigation that should result in an SSL error. // Now do a navigation that should result in an SSL error.
GURL url_with_mismatched_cert = GURL url_with_mismatched_cert =
...@@ -37,9 +40,23 @@ IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, Https) { ...@@ -37,9 +40,23 @@ IN_PROC_BROWSER_TEST_F(WebLayerBrowserTest, Https) {
NavigateAndWaitForFailure(url_with_mismatched_cert, shell()); NavigateAndWaitForFailure(url_with_mismatched_cert, shell());
// TODO(blundell): Adapt the testing of the interstitial appearing from // First check that there *is* an interstitial.
// //chrome's ssl_browsertest.cc:(1462-1465) once the interstitial EXPECT_TRUE(IsShowingSecurityInterstitial(shell()->browser_controller()));
// functionality is brought up.
// Now verify that the interstitial is in fact an SSL interstitial.
EXPECT_TRUE(IsShowingSSLInterstitial(shell()->browser_controller()));
// TODO(blundell): Check the security state once security state is available
// via the public WebLayer API, following the example of //chrome's
// ssl_browsertest.cc's CheckAuthenticationBrokenState() function.
// TODO(blundell): Bring up test of the "Take me back" functionality
// following the example of //chrome's ssl_browsertest.cc:1467, once that
// functionality is implemented in weblayer.
// Check that it's possible to navigate to a new page.
NavigateAndWaitForCompletion(initial_url, shell());
EXPECT_FALSE(IsShowingSecurityInterstitial(shell()->browser_controller()));
} }
} // namespace weblayer } // namespace weblayer
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment