Commit df6d3858 authored by Siddhartha's avatar Siddhartha Committed by Commit Bot

Move out load of bundled assistant proto to the component updater

This CL is moving lifting out the loading from the resource bundle to
the corresponding 'ssl_error_assistant_component'.

The previous implementation was loading on-demand the bundled proto
when needed. But, when the 'ssl_error_assistant_component' is ready, it's
setting the received proto. As no SSL error occured, the bundled proto is
not loaded and must be loaded on the UI thread.

This is causing jank on the UI thread. Which can be seen on the bug 888555.

The current proposition is to keep the bundle loading on-demand since
error paths are not the common ones. But, for the
'ssl_error_assistant_component' path we proposed to also read the bundled
proto and choose the most recent one before sending it to the error
assistant on the UI thread.

That way, most of the job is done before getting on the UI thread.

NOTE: ReadErrorAssistantProtoFromResourceBundle is thread safe and can be
executed on any thread. It can also be executed twice.

R=fdoray@chromium.org, meacer@chromium.org
CC=carlosil@chromium.org, agl@chromium.org

Bug: 888555
Change-Id: Icd994f93c849b3c4d8b01d7921dff69f571397a8
Reviewed-on: https://chromium-review.googlesource.com/c/1247025
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Reviewed-by: default avatarMustafa Emre Acer <meacer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597109}
parent 827c7c93
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "chrome/browser/ssl/ssl_error_assistant.h"
#include "chrome/browser/ssl/ssl_error_handler.h" #include "chrome/browser/ssl/ssl_error_handler.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -46,6 +47,16 @@ void LoadProtoFromDisk(const base::FilePath& pb_path) { ...@@ -46,6 +47,16 @@ void LoadProtoFromDisk(const base::FilePath& pb_path) {
DVLOG(1) << "Failed parsing proto " << pb_path.value(); DVLOG(1) << "Failed parsing proto " << pb_path.value();
return; return;
} }
// Retrieve the default proto from the resource bundle and keep the most
// recent version. This is required since the component updater may still have
// an older version.
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> default_proto =
SSLErrorAssistant::GetErrorAssistantProtoFromResourceBundle();
if (default_proto && default_proto->version_id() > proto->version_id()) {
proto = std::move(default_proto);
}
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI}) base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI})
->PostTask(FROM_HERE, ->PostTask(FROM_HERE,
base::BindOnce(&SSLErrorHandler::SetErrorAssistantProto, base::BindOnce(&SSLErrorHandler::SetErrorAssistantProto,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/android/jni_string.h" #include "base/android/jni_string.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/ssl/ssl_error_assistant.h"
#include "chrome/browser/ssl/ssl_error_handler.h" #include "chrome/browser/ssl/ssl_error_handler.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "jni/CaptivePortalHelper_jni.h" #include "jni/CaptivePortalHelper_jni.h"
...@@ -26,6 +27,13 @@ void JNI_CaptivePortalHelper_SetCaptivePortalCertificateForTesting( ...@@ -26,6 +27,13 @@ void JNI_CaptivePortalHelper_SetCaptivePortalCertificateForTesting(
JNIEnv* env, JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller, const base::android::JavaParamRef<jclass>& jcaller,
const base::android::JavaParamRef<jstring>& jhash) { const base::android::JavaParamRef<jstring>& jhash) {
auto default_proto =
SSLErrorAssistant::GetErrorAssistantProtoFromResourceBundle();
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(SSLErrorHandler::SetErrorAssistantProto,
std::move(default_proto)));
const std::string hash = ConvertJavaStringToUTF8(env, jhash); const std::string hash = ConvertJavaStringToUTF8(env, jhash);
auto config_proto = auto config_proto =
std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>(); std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
......
This diff is collapsed.
...@@ -123,19 +123,6 @@ LoadDynamicInterstitialList( ...@@ -123,19 +123,6 @@ LoadDynamicInterstitialList(
return dynamic_interstitial_list; return dynamic_interstitial_list;
} }
// Reads the SSL error assistant configuration from the resource bundle.
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
ReadErrorAssistantProtoFromResourceBundle() {
auto proto = std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(proto);
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
base::StringPiece data =
bundle.GetRawDataResource(IDR_SSL_ERROR_ASSISTANT_PB);
google::protobuf::io::ArrayInputStream stream(data.data(), data.size());
return proto->ParseFromZeroCopyStream(&stream) ? std::move(proto) : nullptr;
}
bool RegexMatchesAny(const std::vector<std::string>& organization_names, bool RegexMatchesAny(const std::vector<std::string>& organization_names,
const std::string& pattern) { const std::string& pattern) {
const re2::RE2 regex(pattern); const re2::RE2 regex(pattern);
...@@ -203,9 +190,10 @@ SSLErrorAssistant::~SSLErrorAssistant() {} ...@@ -203,9 +190,10 @@ SSLErrorAssistant::~SSLErrorAssistant() {}
bool SSLErrorAssistant::IsKnownCaptivePortalCertificate( bool SSLErrorAssistant::IsKnownCaptivePortalCertificate(
const net::SSLInfo& ssl_info) { const net::SSLInfo& ssl_info) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
EnsureInitialized();
CHECK(error_assistant_proto_);
if (!captive_portal_spki_hashes_) { if (!captive_portal_spki_hashes_) {
error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle();
CHECK(error_assistant_proto_);
captive_portal_spki_hashes_ = captive_portal_spki_hashes_ =
LoadCaptivePortalCertHashes(*error_assistant_proto_); LoadCaptivePortalCertHashes(*error_assistant_proto_);
} }
...@@ -219,10 +207,10 @@ SSLErrorAssistant::MatchDynamicInterstitial(const net::SSLInfo& ssl_info, ...@@ -219,10 +207,10 @@ SSLErrorAssistant::MatchDynamicInterstitial(const net::SSLInfo& ssl_info,
// Load the dynamic interstitial data from SSL error assistant proto if it's // Load the dynamic interstitial data from SSL error assistant proto if it's
// not already loaded. // not already loaded.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!dynamic_interstitial_list_) { EnsureInitialized();
if (!error_assistant_proto_) CHECK(error_assistant_proto_);
error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle();
if (!dynamic_interstitial_list_) {
DCHECK(error_assistant_proto_); DCHECK(error_assistant_proto_);
dynamic_interstitial_list_ = dynamic_interstitial_list_ =
LoadDynamicInterstitialList(*error_assistant_proto_); LoadDynamicInterstitialList(*error_assistant_proto_);
...@@ -270,11 +258,12 @@ const std::string SSLErrorAssistant::MatchKnownMITMSoftware( ...@@ -270,11 +258,12 @@ const std::string SSLErrorAssistant::MatchKnownMITMSoftware(
return std::string(); return std::string();
} }
EnsureInitialized();
CHECK(error_assistant_proto_);
// Load MITM software data from the SSL error assistant proto. // Load MITM software data from the SSL error assistant proto.
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (!mitm_software_list_) { if (!mitm_software_list_) {
if (!error_assistant_proto_)
error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle();
DCHECK(error_assistant_proto_); DCHECK(error_assistant_proto_);
mitm_software_list_ = LoadMITMSoftwareList(*error_assistant_proto_); mitm_software_list_ = LoadMITMSoftwareList(*error_assistant_proto_);
} }
...@@ -322,21 +311,23 @@ const std::string SSLErrorAssistant::MatchKnownMITMSoftware( ...@@ -322,21 +311,23 @@ const std::string SSLErrorAssistant::MatchKnownMITMSoftware(
return std::string(); return std::string();
} }
// static
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
SSLErrorAssistant::GetErrorAssistantProtoFromResourceBundle() {
// Reads the SSL error assistant configuration from the resource bundle.
auto proto = std::make_unique<chrome_browser_ssl::SSLErrorAssistantConfig>();
DCHECK(proto);
ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
base::StringPiece data =
bundle.GetRawDataResource(IDR_SSL_ERROR_ASSISTANT_PB);
google::protobuf::io::ArrayInputStream stream(data.data(), data.size());
return proto->ParseFromZeroCopyStream(&stream) ? std::move(proto) : nullptr;
}
void SSLErrorAssistant::SetErrorAssistantProto( void SSLErrorAssistant::SetErrorAssistantProto(
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) { std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
CHECK(proto); CHECK(proto);
if (!error_assistant_proto_) {
// If the user hasn't seen an SSL error and a component update is available,
// the local resource bundle won't have been read and error_assistant_proto_
// will be null. It's possible that the local resource bundle has a higher
// version_id than the component updater component, so load the local
// resource bundle once to compare versions.
// TODO(meacer): Ideally, ReadErrorAssistantProtoFromResourceBundle should
// only be called once and not on the UI thread. Move the call to the
// component updater component.
error_assistant_proto_ = ReadErrorAssistantProtoFromResourceBundle();
}
// Ignore versions that are not new. INT_MAX is used by tests, so always allow // Ignore versions that are not new. INT_MAX is used by tests, so always allow
// it. // it.
...@@ -356,6 +347,11 @@ void SSLErrorAssistant::SetErrorAssistantProto( ...@@ -356,6 +347,11 @@ void SSLErrorAssistant::SetErrorAssistantProto(
LoadDynamicInterstitialList(*error_assistant_proto_); LoadDynamicInterstitialList(*error_assistant_proto_);
} }
void SSLErrorAssistant::EnsureInitialized() {
if (!error_assistant_proto_)
error_assistant_proto_ = GetErrorAssistantProtoFromResourceBundle();
}
void SSLErrorAssistant::ResetForTesting() { void SSLErrorAssistant::ResetForTesting() {
error_assistant_proto_.reset(); error_assistant_proto_.reset();
mitm_software_list_.reset(); mitm_software_list_.reset();
......
...@@ -88,11 +88,18 @@ class SSLErrorAssistant { ...@@ -88,11 +88,18 @@ class SSLErrorAssistant {
void SetErrorAssistantProto( void SetErrorAssistantProto(
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto); std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> proto);
// Returns the SSL error assistant config stored in the resource bundle. This
// function is thread-safe and can safely be called multiple times.
static std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
GetErrorAssistantProtoFromResourceBundle();
// Testing methods: // Testing methods:
void ResetForTesting(); void ResetForTesting();
int GetErrorAssistantProtoVersionIdForTesting() const; int GetErrorAssistantProtoVersionIdForTesting() const;
private: private:
void EnsureInitialized();
// SPKI hashes belonging to certs treated as captive portals. Null until the // SPKI hashes belonging to certs treated as captive portals. Null until the
// first time ShouldDisplayCaptiveProtalInterstitial() or // first time ShouldDisplayCaptiveProtalInterstitial() or
// SetErrorAssistantProto() is called. // SetErrorAssistantProto() is called.
......
...@@ -233,6 +233,7 @@ class ConfigSingleton { ...@@ -233,6 +233,7 @@ class ConfigSingleton {
void SetErrorAssistantProto( void SetErrorAssistantProto(
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig>
error_assistant_proto); error_assistant_proto);
void SetEnterpriseManagedForTesting(bool enterprise_managed); void SetEnterpriseManagedForTesting(bool enterprise_managed);
bool IsEnterpriseManagedFlagSetForTesting() const; bool IsEnterpriseManagedFlagSetForTesting() const;
int GetErrorAssistantProtoVersionIdForTesting() const; int GetErrorAssistantProtoVersionIdForTesting() const;
...@@ -726,6 +727,7 @@ bool SSLErrorHandler::IsTimerRunningForTesting() const { ...@@ -726,6 +727,7 @@ bool SSLErrorHandler::IsTimerRunningForTesting() const {
return timer_.IsRunning(); return timer_.IsRunning();
} }
// static
void SSLErrorHandler::SetErrorAssistantProto( void SSLErrorHandler::SetErrorAssistantProto(
std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> config_proto) { std::unique_ptr<chrome_browser_ssl::SSLErrorAssistantConfig> config_proto) {
g_config.Pointer()->SetErrorAssistantProto(std::move(config_proto)); g_config.Pointer()->SetErrorAssistantProto(std::move(config_proto));
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "chrome/browser/captive_portal/captive_portal_service.h" #include "chrome/browser/captive_portal/captive_portal_service.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ssl/common_name_mismatch_handler.h" #include "chrome/browser/ssl/common_name_mismatch_handler.h"
#include "chrome/browser/ssl/ssl_error_assistant.h"
#include "chrome/browser/ssl/ssl_error_assistant.pb.h" #include "chrome/browser/ssl/ssl_error_assistant.pb.h"
#include "chrome/common/buildflags.h" #include "chrome/common/buildflags.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
...@@ -368,6 +369,9 @@ class SSLErrorAssistantProtoTest : public ChromeRenderViewHostTestHarness { ...@@ -368,6 +369,9 @@ class SSLErrorAssistantProtoTest : public ChromeRenderViewHostTestHarness {
void SetUp() override { void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
SSLErrorHandler::ResetConfigForTesting(); SSLErrorHandler::ResetConfigForTesting();
SSLErrorHandler::SetErrorAssistantProto(
SSLErrorAssistant::GetErrorAssistantProtoFromResourceBundle());
SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta()); SSLErrorHandler::SetInterstitialDelayForTesting(base::TimeDelta());
ResetErrorHandlerFromFile(kOkayCertName, ResetErrorHandlerFromFile(kOkayCertName,
net::CERT_STATUS_COMMON_NAME_INVALID); net::CERT_STATUS_COMMON_NAME_INVALID);
......
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