Commit 2bb45c61 authored by Tim Volodine's avatar Tim Volodine Committed by Commit Bot

[WebLayer] Implement safebrowsing for renderer initiated url loads.

Make sure to add a renderer-side safebrowsing throttle in order
to check renderer initiated url loads using the safebrowsing API.
This also ensures that resource requests for e.g. .js and .svg
files are also checked. This approach matches the behavior in
WebView and Chrome. Due to the addition of methods the original
safebrowsing initialization sequence is slightly changed (see
below for details). Additionally the ResourceContext destruction
has to happen on the IO thread (see below for details).

In particular in this patch:
- Add and implement ExposeInterfacesToRenderer method to make
  sure renderer can execute safebrowsing calls.
- Move safebrowsing_service initialization to the
  ExposeInterfacesToRenderer() method because it is executed
  before CreateURLLoaderThrottles.
- Implement UrlLoaderThrottleProvider in weblayer/renderer/
  which amongst other things adds the
  safe_browsing::RendererURLLoaderThrottle.
- Implement RenderThreadStarted() and
  CreateURLLoaderThrottleProvider() methods for
  ContentRendererClient.
- Update build and deps files accordingly.
- Also make sure to destroy ResourceContext on the IO thread
  (otherwise profile destruction sequence can result in a
  DCHECK, see crbug.com/1029317).

BUG=1015418,1028659,1029317

Change-Id: I67482a450d1974a8b14cb07f4fbedd14e4983e7e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1937173
Commit-Queue: Tim Volodine <timvolodine@chromium.org>
Reviewed-by: default avatarClark DuVall <cduvall@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#720726}
parent ac0af928
...@@ -208,6 +208,8 @@ jumbo_static_library("weblayer_lib") { ...@@ -208,6 +208,8 @@ jumbo_static_library("weblayer_lib") {
"browser/safe_browsing/url_checker_delegate_impl.cc", "browser/safe_browsing/url_checker_delegate_impl.cc",
"browser/safe_browsing/url_checker_delegate_impl.h", "browser/safe_browsing/url_checker_delegate_impl.h",
"browser/weblayer_impl_android.cc", "browser/weblayer_impl_android.cc",
"renderer/url_loader_throttle_provider.cc",
"renderer/url_loader_throttle_provider.h",
] ]
} }
...@@ -291,7 +293,9 @@ jumbo_static_library("weblayer_lib") { ...@@ -291,7 +293,9 @@ jumbo_static_library("weblayer_lib") {
"//components/safe_browsing/android:safe_browsing_api_handler", "//components/safe_browsing/android:safe_browsing_api_handler",
"//components/safe_browsing/browser", "//components/safe_browsing/browser",
"//components/safe_browsing/browser:network_context", "//components/safe_browsing/browser:network_context",
"//components/safe_browsing/common",
"//components/safe_browsing/db:database_manager", "//components/safe_browsing/db:database_manager",
"//components/safe_browsing/renderer:throttles",
"//components/version_info/android:channel_getter", "//components/version_info/android:channel_getter",
] ]
} }
......
...@@ -242,16 +242,7 @@ ContentBrowserClientImpl::CreateURLLoaderThrottles( ...@@ -242,16 +242,7 @@ ContentBrowserClientImpl::CreateURLLoaderThrottles(
if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing) && if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing) &&
IsSafebrowsingSupported()) { IsSafebrowsingSupported()) {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
if (!safe_browsing_service_) { result.push_back(GetSafeBrowsingService()->CreateURLLoaderThrottle(
// TODO(timvolodine): consider creating SafeBrowsingService elsewhere
// (especially in multiplatform support).
// Note: Initialize() needs to happen on UI thread.
safe_browsing_service_ =
std::make_unique<SafeBrowsingService>(GetUserAgent());
safe_browsing_service_->Initialize();
}
result.push_back(safe_browsing_service_->CreateURLLoaderThrottle(
browser_context->GetResourceContext(), wc_getter, frame_tree_node_id)); browser_context->GetResourceContext(), wc_getter, frame_tree_node_id));
#endif #endif
} }
...@@ -329,6 +320,31 @@ ContentBrowserClientImpl::GetGeneratedCodeCacheSettings( ...@@ -329,6 +320,31 @@ ContentBrowserClientImpl::GetGeneratedCodeCacheSettings(
true, 0, ProfileImpl::GetCachePath(context)); true, 0, ProfileImpl::GetCachePath(context));
} }
void ContentBrowserClientImpl::ExposeInterfacesToRenderer(
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) {
if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing) &&
IsSafebrowsingSupported()) {
#if defined(OS_ANDROID)
GetSafeBrowsingService()->AddInterface(registry, render_process_host);
#endif
}
}
#if defined(OS_ANDROID)
SafeBrowsingService* ContentBrowserClientImpl::GetSafeBrowsingService() {
if (!safe_browsing_service_) {
// Create and initialize safe_browsing_service on first get.
// Note: Initialize() needs to happen on UI thread.
safe_browsing_service_ =
std::make_unique<SafeBrowsingService>(GetUserAgent());
safe_browsing_service_->Initialize();
}
return safe_browsing_service_.get();
}
#endif
#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,
......
...@@ -70,6 +70,10 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient { ...@@ -70,6 +70,10 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient {
CreateThrottlesForNavigation(content::NavigationHandle* handle) override; CreateThrottlesForNavigation(content::NavigationHandle* handle) override;
content::GeneratedCodeCacheSettings GetGeneratedCodeCacheSettings( content::GeneratedCodeCacheSettings GetGeneratedCodeCacheSettings(
content::BrowserContext* context) override; content::BrowserContext* context) override;
void ExposeInterfacesToRenderer(
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) override;
#if defined(OS_LINUX) || defined(OS_ANDROID) #if defined(OS_LINUX) || defined(OS_ANDROID)
void GetAdditionalMappedFilesForChildProcess( void GetAdditionalMappedFilesForChildProcess(
...@@ -94,6 +98,7 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient { ...@@ -94,6 +98,7 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient {
MainParams* params_; MainParams* params_;
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
SafeBrowsingService* GetSafeBrowsingService();
std::unique_ptr<SafeBrowsingService> safe_browsing_service_; std::unique_ptr<SafeBrowsingService> safe_browsing_service_;
#endif #endif
}; };
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "components/user_prefs/user_prefs.h" #include "components/user_prefs/user_prefs.h"
#include "components/web_cache/browser/web_cache_manager.h" #include "components/web_cache/browser/web_cache_manager.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.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"
...@@ -104,8 +105,9 @@ bool IsNameValid(const std::string& name) { ...@@ -104,8 +105,9 @@ bool IsNameValid(const std::string& name) {
class ProfileImpl::BrowserContextImpl : public content::BrowserContext { class ProfileImpl::BrowserContextImpl : public content::BrowserContext {
public: public:
BrowserContextImpl(ProfileImpl* profile_impl, const base::FilePath& path) BrowserContextImpl(ProfileImpl* profile_impl, const base::FilePath& path)
: profile_impl_(profile_impl), path_(path) { : profile_impl_(profile_impl),
resource_context_ = std::make_unique<ResourceContextImpl>(); path_(path),
resource_context_(new ResourceContextImpl()) {
content::BrowserContext::Initialize(this, path_); content::BrowserContext::Initialize(this, path_);
CreateUserPrefService(); CreateUserPrefService();
...@@ -207,7 +209,15 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext { ...@@ -207,7 +209,15 @@ class ProfileImpl::BrowserContextImpl : public content::BrowserContext {
ProfileImpl* const profile_impl_; ProfileImpl* const profile_impl_;
base::FilePath path_; base::FilePath path_;
std::unique_ptr<ResourceContextImpl> resource_context_; // ResourceContext needs to be deleted on the IO thread in general (and in
// particular due to the destruction of the safebrowsing mojo interface
// that has been added in ContentBrowserClient::ExposeInterfacesToRenderer
// on IO thread, see crbug.com/1029317). Also this is similar to how Chrome
// handles ProfileIOData.
// TODO(timvolodine): consider a more general Profile shutdown/destruction
// sequence for the IO/UI bits (crbug.com/1029879).
std::unique_ptr<ResourceContextImpl, content::BrowserThread::DeleteOnIOThread>
resource_context_;
DownloadManagerDelegateImpl download_delegate_; DownloadManagerDelegateImpl download_delegate_;
SSLHostStateDelegateImpl ssl_host_state_delegate_; SSLHostStateDelegateImpl ssl_host_state_delegate_;
std::unique_ptr<PrefService> user_pref_service_; std::unique_ptr<PrefService> user_pref_service_;
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include "components/safe_browsing/browser/browser_url_loader_throttle.h" #include "components/safe_browsing/browser/browser_url_loader_throttle.h"
#include "components/safe_browsing/browser/mojo_safe_browsing_impl.h" #include "components/safe_browsing/browser/mojo_safe_browsing_impl.h"
#include "components/safe_browsing/browser/safe_browsing_network_context.h" #include "components/safe_browsing/browser/safe_browsing_network_context.h"
#include "content/public/browser/browser_context.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"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h" #include "content/public/browser/resource_context.h"
#include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h"
...@@ -150,4 +152,19 @@ void SafeBrowsingService::CreateURLLoaderFactoryForIO( ...@@ -150,4 +152,19 @@ void SafeBrowsingService::CreateURLLoaderFactoryForIO(
std::move(receiver), std::move(url_loader_factory_params)); std::move(receiver), std::move(url_loader_factory_params));
} }
void SafeBrowsingService::AddInterface(
service_manager::BinderRegistry* registry,
content::RenderProcessHost* render_process_host) {
content::ResourceContext* resource_context =
render_process_host->GetBrowserContext()->GetResourceContext();
registry->AddInterface(
base::BindRepeating(
&safe_browsing::MojoSafeBrowsingImpl::MaybeCreate,
render_process_host->GetID(), resource_context,
base::BindRepeating(
&SafeBrowsingService::GetSafeBrowsingUrlCheckerDelegate,
base::Unretained(this))),
base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}));
}
} // namespace weblayer } // namespace weblayer
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
#include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "weblayer/browser/safe_browsing/safe_browsing_ui_manager.h" #include "weblayer/browser/safe_browsing/safe_browsing_ui_manager.h"
namespace content { namespace content {
class RenderProcessHost;
class ResourceContext; class ResourceContext;
} }
...@@ -47,6 +49,8 @@ class SafeBrowsingService { ...@@ -47,6 +49,8 @@ class SafeBrowsingService {
content::ResourceContext* resource_context, content::ResourceContext* resource_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter, const base::RepeatingCallback<content::WebContents*()>& wc_getter,
int frame_tree_node_id); int frame_tree_node_id);
void AddInterface(service_manager::BinderRegistry* registry,
content::RenderProcessHost* render_process_host);
private: private:
SafeBrowsingUIManager* GetSafeBrowsingUIManager(); SafeBrowsingUIManager* GetSafeBrowsingUIManager();
...@@ -67,8 +71,8 @@ class SafeBrowsingService { ...@@ -67,8 +71,8 @@ class SafeBrowsingService {
// thread. // thread.
scoped_refptr<SafeBrowsingUIManager> ui_manager_; scoped_refptr<SafeBrowsingUIManager> ui_manager_;
// This is what owns the URLRequestContext inside the network service. This is // This is what owns the URLRequestContext inside the network service. This
// used by SimpleURLLoader for Safe Browsing requests. // is used by SimpleURLLoader for Safe Browsing requests.
std::unique_ptr<safe_browsing::SafeBrowsingNetworkContext> network_context_; std::unique_ptr<safe_browsing::SafeBrowsingNetworkContext> network_context_;
// Accessed on IO thread only. // Accessed on IO thread only.
......
...@@ -4,10 +4,15 @@ include_rules = [ ...@@ -4,10 +4,15 @@ include_rules = [
# long-term, componentize these strings/resources as part of componentizing # long-term, componentize these strings/resources as part of componentizing
# that implementation and remove the need for this dependency. # that implementation and remove the need for this dependency.
"+android_webview/grit", "+android_webview/grit",
"+components/safe_browsing/common",
"+components/safe_browsing/renderer",
"+components/security_interstitials/content/renderer", "+components/security_interstitials/content/renderer",
"+components/security_interstitials/core/common", "+components/security_interstitials/core/common",
"+content/public/renderer", "+content/public/renderer",
# needed for safebrowsing
"+mojo/public/cpp/bindings",
"+net/base", "+net/base",
"+third_party/blink/public/common", "+third_party/blink/public/common",
"+third_party/blink/public/platform",
"+ui/base", "+ui/base",
] ]
...@@ -4,17 +4,22 @@ ...@@ -4,17 +4,22 @@
#include "weblayer/renderer/content_renderer_client_impl.h" #include "weblayer/renderer/content_renderer_client_impl.h"
#include "base/feature_list.h"
#include "base/i18n/rtl.h" #include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/public/renderer/render_thread.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "third_party/blink/public/platform/platform.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "weblayer/common/features.h"
#include "weblayer/renderer/ssl_error_helper.h" #include "weblayer/renderer/ssl_error_helper.h"
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "android_webview/grit/aw_resources.h" #include "android_webview/grit/aw_resources.h"
#include "android_webview/grit/aw_strings.h" #include "android_webview/grit/aw_strings.h"
#include "weblayer/renderer/url_loader_throttle_provider.h"
#endif #endif
namespace weblayer { namespace weblayer {
...@@ -103,4 +108,25 @@ void ContentRendererClientImpl::PrepareErrorPage( ...@@ -103,4 +108,25 @@ void ContentRendererClientImpl::PrepareErrorPage(
#endif #endif
} }
void ContentRendererClientImpl::RenderThreadStarted() {
browser_interface_broker_ =
blink::Platform::Current()->GetBrowserInterfaceBroker();
}
std::unique_ptr<content::URLLoaderThrottleProvider>
ContentRendererClientImpl::CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType provider_type) {
if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing)) {
#if defined(OS_ANDROID)
// Note: currently the throttle provider is only needed for safebrowsing.
return std::make_unique<URLLoaderThrottleProvider>(
browser_interface_broker_.get(), provider_type);
#else
return nullptr;
#endif
}
return nullptr;
}
} // namespace weblayer } // namespace weblayer
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/content_renderer_client.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
namespace weblayer { namespace weblayer {
...@@ -22,8 +23,15 @@ class ContentRendererClientImpl : public content::ContentRendererClient { ...@@ -22,8 +23,15 @@ class ContentRendererClientImpl : public content::ContentRendererClient {
const blink::WebURLError& error, const blink::WebURLError& error,
const std::string& http_method, const std::string& http_method,
std::string* error_html) override; std::string* error_html) override;
void RenderThreadStarted() override;
std::unique_ptr<content::URLLoaderThrottleProvider>
CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType provider_type) override;
private: private:
scoped_refptr<blink::ThreadSafeBrowserInterfaceBrokerProxy>
browser_interface_broker_;
DISALLOW_COPY_AND_ASSIGN(ContentRendererClientImpl); DISALLOW_COPY_AND_ASSIGN(ContentRendererClientImpl);
}; };
......
// 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/url_loader_throttle_provider.h"
#include <memory>
#include "components/safe_browsing/renderer/renderer_url_loader_throttle.h"
#include "content/public/renderer/render_thread.h"
namespace weblayer {
URLLoaderThrottleProvider::URLLoaderThrottleProvider(
blink::ThreadSafeBrowserInterfaceBrokerProxy* broker,
content::URLLoaderThrottleProviderType type)
: type_(type) {
DETACH_FROM_THREAD(thread_checker_);
broker->GetInterface(safe_browsing_remote_.InitWithNewPipeAndPassReceiver());
}
URLLoaderThrottleProvider::URLLoaderThrottleProvider(
const URLLoaderThrottleProvider& other)
: type_(other.type_) {
DETACH_FROM_THREAD(thread_checker_);
if (other.safe_browsing_) {
other.safe_browsing_->Clone(
safe_browsing_remote_.InitWithNewPipeAndPassReceiver());
}
}
std::unique_ptr<content::URLLoaderThrottleProvider>
URLLoaderThrottleProvider::Clone() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (safe_browsing_remote_)
safe_browsing_.Bind(std::move(safe_browsing_remote_));
return base::WrapUnique(new URLLoaderThrottleProvider(*this));
}
URLLoaderThrottleProvider::~URLLoaderThrottleProvider() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
}
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
URLLoaderThrottleProvider::CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
bool is_frame_resource = content::IsResourceTypeFrame(resource_type);
DCHECK(!is_frame_resource ||
type_ == content::URLLoaderThrottleProviderType::kFrame);
if (!is_frame_resource) {
if (safe_browsing_remote_)
safe_browsing_.Bind(std::move(safe_browsing_remote_));
throttles.push_back(
std::make_unique<safe_browsing::RendererURLLoaderThrottle>(
safe_browsing_.get(), render_frame_id));
}
return throttles;
}
void URLLoaderThrottleProvider::SetOnline(bool is_online) {}
} // 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_URL_LOADER_THROTTLE_PROVIDER_H_
#define WEBLAYER_RENDERER_URL_LOADER_THROTTLE_PROVIDER_H_
#include "base/threading/thread_checker.h"
#include "components/safe_browsing/common/safe_browsing.mojom.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
namespace weblayer {
// Instances must be constructed on the render thread, and then used and
// destructed on a single thread, which can be different from the render thread.
class URLLoaderThrottleProvider : public content::URLLoaderThrottleProvider {
public:
URLLoaderThrottleProvider(
blink::ThreadSafeBrowserInterfaceBrokerProxy* broker,
content::URLLoaderThrottleProviderType type);
~URLLoaderThrottleProvider() override;
// content::URLLoaderThrottleProvider implementation.
std::unique_ptr<content::URLLoaderThrottleProvider> Clone() override;
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) override;
void SetOnline(bool is_online) override;
private:
// This copy constructor works in conjunction with Clone(), not intended for
// general use.
URLLoaderThrottleProvider(const URLLoaderThrottleProvider& other);
content::URLLoaderThrottleProviderType type_;
mojo::PendingRemote<safe_browsing::mojom::SafeBrowsing> safe_browsing_remote_;
mojo::Remote<safe_browsing::mojom::SafeBrowsing> safe_browsing_;
THREAD_CHECKER(thread_checker_);
DISALLOW_ASSIGN(URLLoaderThrottleProvider);
};
} // namespace weblayer
#endif // WEBLAYER_RENDERER_URL_LOADER_THROTTLE_PROVIDER_H_
\ No newline at end of file
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