feat: HTTP preconnect feature minimal for electronjs (#18671)
This commit is contained in:
parent
c57db7f163
commit
cddbddc543
17 changed files with 377 additions and 1 deletions
2
BUILD.gn
2
BUILD.gn
|
@ -349,6 +349,8 @@ source_set("electron_lib") {
|
||||||
"//chrome/services/printing/public/mojom",
|
"//chrome/services/printing/public/mojom",
|
||||||
"//components/certificate_transparency",
|
"//components/certificate_transparency",
|
||||||
"//components/net_log",
|
"//components/net_log",
|
||||||
|
"//components/network_hints/common",
|
||||||
|
"//components/network_hints/renderer",
|
||||||
"//components/network_session_configurator/common",
|
"//components/network_session_configurator/common",
|
||||||
"//components/prefs",
|
"//components/prefs",
|
||||||
"//components/spellcheck/renderer",
|
"//components/spellcheck/renderer",
|
||||||
|
|
|
@ -37,6 +37,12 @@ static_library("chrome") {
|
||||||
"//chrome/browser/net/proxy_config_monitor.h",
|
"//chrome/browser/net/proxy_config_monitor.h",
|
||||||
"//chrome/browser/net/proxy_service_factory.cc",
|
"//chrome/browser/net/proxy_service_factory.cc",
|
||||||
"//chrome/browser/net/proxy_service_factory.h",
|
"//chrome/browser/net/proxy_service_factory.h",
|
||||||
|
"//chrome/browser/predictors/preconnect_manager.cc",
|
||||||
|
"//chrome/browser/predictors/preconnect_manager.h",
|
||||||
|
"//chrome/browser/predictors/proxy_lookup_client_impl.cc",
|
||||||
|
"//chrome/browser/predictors/proxy_lookup_client_impl.h",
|
||||||
|
"//chrome/browser/predictors/resolve_host_client_impl.cc",
|
||||||
|
"//chrome/browser/predictors/resolve_host_client_impl.h",
|
||||||
"//chrome/browser/printing/printing_service.cc",
|
"//chrome/browser/printing/printing_service.cc",
|
||||||
"//chrome/browser/printing/printing_service.h",
|
"//chrome/browser/printing/printing_service.h",
|
||||||
"//chrome/browser/ssl/security_state_tab_helper.cc",
|
"//chrome/browser/ssl/security_state_tab_helper.cc",
|
||||||
|
@ -57,6 +63,7 @@ static_library("chrome") {
|
||||||
"//content/public/browser",
|
"//content/public/browser",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
|
"//chrome/browser:resource_prefetch_predictor_proto",
|
||||||
"//components/feature_engagement:buildflags",
|
"//components/feature_engagement:buildflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,20 @@ session.defaultSession.on('will-download', (event, item, webContents) => {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Event: 'preconnect'
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
* `event` Event
|
||||||
|
* `preconnectUrl` String - The URL being requested for preconnection by the
|
||||||
|
renderer.
|
||||||
|
* `allowCredentials` Boolean - True if the renderer is requesting that the
|
||||||
|
connection include credentials (see the
|
||||||
|
[spec](https://w3c.github.io/resource-hints/#preconnect) for more details.)
|
||||||
|
|
||||||
|
Emitted when a render process requests preconnection to a URL, generally due to
|
||||||
|
a [resource hint](https://w3c.github.io/resource-hints/).
|
||||||
|
|
||||||
### Instance Methods
|
### Instance Methods
|
||||||
|
|
||||||
The following methods are available on instances of `Session`:
|
The following methods are available on instances of `Session`:
|
||||||
|
@ -238,6 +252,14 @@ window.webContents.session.enableNetworkEmulation({
|
||||||
window.webContents.session.enableNetworkEmulation({ offline: true })
|
window.webContents.session.enableNetworkEmulation({ offline: true })
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `ses.preconnect(options)`
|
||||||
|
|
||||||
|
* `options` Object
|
||||||
|
* `url` String - URL for preconnect. Only the origin is relevant for opening the socket.
|
||||||
|
* `numSockets` Number (optional) - number of sockets to preconnect. Must be between 1 and 6. Defaults to 1.
|
||||||
|
|
||||||
|
Preconnects the given number of sockets to an origin.
|
||||||
|
|
||||||
#### `ses.disableNetworkEmulation()`
|
#### `ses.disableNetworkEmulation()`
|
||||||
|
|
||||||
Disables any network emulation already active for the `session`. Resets to
|
Disables any network emulation already active for the `session`. Resets to
|
||||||
|
|
|
@ -276,6 +276,8 @@ filenames = {
|
||||||
"shell/browser/relauncher_win.cc",
|
"shell/browser/relauncher_win.cc",
|
||||||
"shell/browser/relauncher.cc",
|
"shell/browser/relauncher.cc",
|
||||||
"shell/browser/relauncher.h",
|
"shell/browser/relauncher.h",
|
||||||
|
"shell/browser/renderer_host/electron_render_message_filter.cc",
|
||||||
|
"shell/browser/renderer_host/electron_render_message_filter.h",
|
||||||
"shell/browser/session_preferences.cc",
|
"shell/browser/session_preferences.cc",
|
||||||
"shell/browser/session_preferences.h",
|
"shell/browser/session_preferences.h",
|
||||||
"shell/browser/special_storage_policy.cc",
|
"shell/browser/special_storage_policy.cc",
|
||||||
|
|
|
@ -67,6 +67,7 @@ worker_context_will_destroy.patch
|
||||||
fix_breakpad_symbol_generation_on_linux_arm.patch
|
fix_breakpad_symbol_generation_on_linux_arm.patch
|
||||||
frame_host_manager.patch
|
frame_host_manager.patch
|
||||||
crashpad_pid_check.patch
|
crashpad_pid_check.patch
|
||||||
|
preconnect_feature.patch
|
||||||
network_service_allow_remote_certificate_verification_logic.patch
|
network_service_allow_remote_certificate_verification_logic.patch
|
||||||
put_back_deleted_colors_for_autofill.patch
|
put_back_deleted_colors_for_autofill.patch
|
||||||
build_win_disable_zc_twophase.patch
|
build_win_disable_zc_twophase.patch
|
||||||
|
|
69
patches/chromium/preconnect_feature.patch
Normal file
69
patches/chromium/preconnect_feature.patch
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexey Kuts <kruntuid@gmail.com>
|
||||||
|
Date: Fri, 26 Jul 2019 22:32:54 +0300
|
||||||
|
Subject: remove references to Profile from PreconnectManager
|
||||||
|
|
||||||
|
The PreconnectManager in Chrome only depends on Profile for testing purposes;
|
||||||
|
this patch removes that dependency so we can reuse it.
|
||||||
|
Ideally we would change this class in upstream to not depend on Profile.
|
||||||
|
|
||||||
|
diff --git a/chrome/browser/predictors/preconnect_manager.cc b/chrome/browser/predictors/preconnect_manager.cc
|
||||||
|
index cdee4d11f2d2..7312fb4e4ea5 100644
|
||||||
|
--- a/chrome/browser/predictors/preconnect_manager.cc
|
||||||
|
+++ b/chrome/browser/predictors/preconnect_manager.cc
|
||||||
|
@@ -71,7 +71,7 @@ PreresolveJob::PreresolveJob(PreresolveJob&& other) = default;
|
||||||
|
PreresolveJob::~PreresolveJob() = default;
|
||||||
|
|
||||||
|
PreconnectManager::PreconnectManager(base::WeakPtr<Delegate> delegate,
|
||||||
|
- Profile* profile)
|
||||||
|
+ content::BrowserContext* profile)
|
||||||
|
: delegate_(std::move(delegate)),
|
||||||
|
profile_(profile),
|
||||||
|
inflight_preresolves_count_(0) {
|
||||||
|
@@ -327,11 +327,13 @@ network::mojom::NetworkContext* PreconnectManager::GetNetworkContext() const {
|
||||||
|
if (network_context_)
|
||||||
|
return network_context_;
|
||||||
|
|
||||||
|
+#if 0
|
||||||
|
if (profile_->AsTestingProfile()) {
|
||||||
|
// We're testing and |network_context_| wasn't set. Return nullptr to avoid
|
||||||
|
// hitting the network.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
return content::BrowserContext::GetDefaultStoragePartition(profile_)
|
||||||
|
->GetNetworkContext();
|
||||||
|
diff --git a/chrome/browser/predictors/preconnect_manager.h b/chrome/browser/predictors/preconnect_manager.h
|
||||||
|
index 51a842d2e44f..097316e0cfb6 100644
|
||||||
|
--- a/chrome/browser/predictors/preconnect_manager.h
|
||||||
|
+++ b/chrome/browser/predictors/preconnect_manager.h
|
||||||
|
@@ -22,6 +22,10 @@
|
||||||
|
|
||||||
|
class Profile;
|
||||||
|
|
||||||
|
+namespace content {
|
||||||
|
+class BrowserContext;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
namespace network {
|
||||||
|
namespace mojom {
|
||||||
|
class NetworkContext;
|
||||||
|
@@ -138,7 +142,7 @@ class PreconnectManager {
|
||||||
|
|
||||||
|
static const size_t kMaxInflightPreresolves = 3;
|
||||||
|
|
||||||
|
- PreconnectManager(base::WeakPtr<Delegate> delegate, Profile* profile);
|
||||||
|
+ PreconnectManager(base::WeakPtr<Delegate> delegate, content::BrowserContext* profile);
|
||||||
|
virtual ~PreconnectManager();
|
||||||
|
|
||||||
|
// Starts preconnect and preresolve jobs keyed by |url|.
|
||||||
|
@@ -202,7 +206,7 @@ class PreconnectManager {
|
||||||
|
network::mojom::NetworkContext* GetNetworkContext() const;
|
||||||
|
|
||||||
|
base::WeakPtr<Delegate> delegate_;
|
||||||
|
- Profile* const profile_;
|
||||||
|
+ content::BrowserContext* const profile_;
|
||||||
|
std::list<PreresolveJobId> queued_jobs_;
|
||||||
|
PreresolveJobMap preresolve_jobs_;
|
||||||
|
std::map<std::string, std::unique_ptr<PreresolveInfo>> preresolve_info_;
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "shell/browser/api/atom_api_session.h"
|
#include "shell/browser/api/atom_api_session.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -594,6 +595,42 @@ v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
|
||||||
return v8::Local<v8::Value>::New(isolate, net_log_);
|
return v8::Local<v8::Value>::New(isolate, net_log_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void StartPreconnectOnUI(
|
||||||
|
scoped_refptr<AtomBrowserContext> browser_context,
|
||||||
|
const GURL& url,
|
||||||
|
int num_sockets_to_preconnect) {
|
||||||
|
std::vector<predictors::PreconnectRequest> requests = {
|
||||||
|
{url.GetOrigin(), num_sockets_to_preconnect, net::NetworkIsolationKey()}};
|
||||||
|
browser_context->GetPreconnectManager()->Start(url, requests);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::Preconnect(const mate::Dictionary& options,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
GURL url;
|
||||||
|
if (!options.Get("url", &url) || !url.is_valid()) {
|
||||||
|
args->ThrowError("Must pass non-empty valid url to session.preconnect.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int num_sockets_to_preconnect = 1;
|
||||||
|
if (options.Get("numSockets", &num_sockets_to_preconnect)) {
|
||||||
|
const int kMinSocketsToPreconnect = 1;
|
||||||
|
const int kMaxSocketsToPreconnect = 6;
|
||||||
|
if (num_sockets_to_preconnect < kMinSocketsToPreconnect ||
|
||||||
|
num_sockets_to_preconnect > kMaxSocketsToPreconnect) {
|
||||||
|
args->ThrowError(
|
||||||
|
base::StringPrintf("numSocketsToPreconnect is outside range [%d,%d]",
|
||||||
|
kMinSocketsToPreconnect, kMaxSocketsToPreconnect));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DCHECK_GT(num_sockets_to_preconnect, 0);
|
||||||
|
base::PostTaskWithTraits(
|
||||||
|
FROM_HERE, {content::BrowserThread::UI},
|
||||||
|
base::BindOnce(&StartPreconnectOnUI, base::RetainedRef(browser_context_),
|
||||||
|
url, num_sockets_to_preconnect));
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
mate::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
|
mate::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
|
||||||
AtomBrowserContext* browser_context) {
|
AtomBrowserContext* browser_context) {
|
||||||
|
@ -664,6 +701,7 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
.SetMethod("loadChromeExtension", &Session::LoadChromeExtension)
|
.SetMethod("loadChromeExtension", &Session::LoadChromeExtension)
|
||||||
#endif
|
#endif
|
||||||
|
.SetMethod("preconnect", &Session::Preconnect)
|
||||||
.SetProperty("cookies", &Session::Cookies)
|
.SetProperty("cookies", &Session::Cookies)
|
||||||
.SetProperty("netLog", &Session::NetLog)
|
.SetProperty("netLog", &Session::NetLog)
|
||||||
.SetProperty("protocol", &Session::Protocol)
|
.SetProperty("protocol", &Session::Protocol)
|
||||||
|
|
|
@ -86,6 +86,7 @@ class Session : public mate::TrackableObject<Session>,
|
||||||
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
|
||||||
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
|
||||||
v8::Local<v8::Value> NetLog(v8::Isolate* isolate);
|
v8::Local<v8::Value> NetLog(v8::Isolate* isolate);
|
||||||
|
void Preconnect(const mate::Dictionary& options, mate::Arguments* args);
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
void LoadChromeExtension(const base::FilePath extension_path);
|
void LoadChromeExtension(const base::FilePath extension_path);
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "shell/app/manifests.h"
|
#include "shell/app/manifests.h"
|
||||||
#include "shell/browser/api/atom_api_app.h"
|
#include "shell/browser/api/atom_api_app.h"
|
||||||
#include "shell/browser/api/atom_api_protocol_ns.h"
|
#include "shell/browser/api/atom_api_protocol_ns.h"
|
||||||
|
#include "shell/browser/api/atom_api_session.h"
|
||||||
#include "shell/browser/api/atom_api_web_contents.h"
|
#include "shell/browser/api/atom_api_web_contents.h"
|
||||||
#include "shell/browser/api/atom_api_web_request_ns.h"
|
#include "shell/browser/api/atom_api_web_request_ns.h"
|
||||||
#include "shell/browser/atom_autofill_driver_factory.h"
|
#include "shell/browser/atom_autofill_driver_factory.h"
|
||||||
|
@ -70,6 +71,7 @@
|
||||||
#include "shell/browser/net/system_network_context_manager.h"
|
#include "shell/browser/net/system_network_context_manager.h"
|
||||||
#include "shell/browser/notifications/notification_presenter.h"
|
#include "shell/browser/notifications/notification_presenter.h"
|
||||||
#include "shell/browser/notifications/platform_notification_service.h"
|
#include "shell/browser/notifications/platform_notification_service.h"
|
||||||
|
#include "shell/browser/renderer_host/electron_render_message_filter.h"
|
||||||
#include "shell/browser/session_preferences.h"
|
#include "shell/browser/session_preferences.h"
|
||||||
#include "shell/browser/ui/devtools_manager_delegate.h"
|
#include "shell/browser/ui/devtools_manager_delegate.h"
|
||||||
#include "shell/browser/web_contents_permission_helper.h"
|
#include "shell/browser/web_contents_permission_helper.h"
|
||||||
|
@ -365,6 +367,9 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
||||||
prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
|
prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
|
||||||
true /* default value */);
|
true /* default value */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host->AddFilter(new ElectronRenderMessageFilter(host->GetBrowserContext()));
|
||||||
|
|
||||||
AddProcessPreferences(host->GetID(), prefs);
|
AddProcessPreferences(host->GetID(), prefs);
|
||||||
// ensure the ProcessPreferences is removed later
|
// ensure the ProcessPreferences is removed later
|
||||||
host->AddObserver(this);
|
host->AddObserver(this);
|
||||||
|
|
|
@ -264,6 +264,13 @@ AtomBlobReader* AtomBrowserContext::GetBlobReader() {
|
||||||
return blob_reader_.get();
|
return blob_reader_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predictors::PreconnectManager* AtomBrowserContext::GetPreconnectManager() {
|
||||||
|
if (!preconnect_manager_.get()) {
|
||||||
|
preconnect_manager_.reset(new predictors::PreconnectManager(nullptr, this));
|
||||||
|
}
|
||||||
|
return preconnect_manager_.get();
|
||||||
|
}
|
||||||
|
|
||||||
content::PushMessagingService* AtomBrowserContext::GetPushMessagingService() {
|
content::PushMessagingService* AtomBrowserContext::GetPushMessagingService() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "base/memory/ref_counted_delete_on_sequence.h"
|
#include "base/memory/ref_counted_delete_on_sequence.h"
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "chrome/browser/net/proxy_config_monitor.h"
|
#include "chrome/browser/net/proxy_config_monitor.h"
|
||||||
|
#include "chrome/browser/predictors/preconnect_manager.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
#include "content/public/browser/resource_context.h"
|
#include "content/public/browser/resource_context.h"
|
||||||
#include "electron/buildflags/buildflags.h"
|
#include "electron/buildflags/buildflags.h"
|
||||||
|
@ -87,6 +88,8 @@ class AtomBrowserContext
|
||||||
AtomBlobReader* GetBlobReader();
|
AtomBlobReader* GetBlobReader();
|
||||||
ResolveProxyHelper* GetResolveProxyHelper();
|
ResolveProxyHelper* GetResolveProxyHelper();
|
||||||
|
|
||||||
|
predictors::PreconnectManager* GetPreconnectManager();
|
||||||
|
|
||||||
// content::BrowserContext:
|
// content::BrowserContext:
|
||||||
base::FilePath GetPath() override;
|
base::FilePath GetPath() override;
|
||||||
bool IsOffTheRecord() override;
|
bool IsOffTheRecord() override;
|
||||||
|
@ -164,6 +167,8 @@ class AtomBrowserContext
|
||||||
// ProxyConfigClient.
|
// ProxyConfigClient.
|
||||||
std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_;
|
std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_;
|
||||||
|
|
||||||
|
std::unique_ptr<predictors::PreconnectManager> preconnect_manager_;
|
||||||
|
|
||||||
std::string user_agent_;
|
std::string user_agent_;
|
||||||
base::FilePath path_;
|
base::FilePath path_;
|
||||||
bool in_memory_ = false;
|
bool in_memory_ = false;
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright (c) 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 "shell/browser/renderer_host/electron_render_message_filter.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/bind.h"
|
||||||
|
#include "base/bind_helpers.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/stl_util.h"
|
||||||
|
#include "chrome/browser/predictors/preconnect_manager.h"
|
||||||
|
#include "components/network_hints/common/network_hints_common.h"
|
||||||
|
#include "components/network_hints/common/network_hints_messages.h"
|
||||||
|
#include "content/public/browser/browser_context.h"
|
||||||
|
#include "shell/browser/api/atom_api_session.h"
|
||||||
|
#include "shell/browser/atom_browser_context.h"
|
||||||
|
#include "shell/common/native_mate_converters/gurl_converter.h"
|
||||||
|
|
||||||
|
using content::BrowserThread;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const uint32_t kRenderFilteredMessageClasses[] = {
|
||||||
|
NetworkHintsMsgStart,
|
||||||
|
};
|
||||||
|
|
||||||
|
void EmitPreconnect(content::BrowserContext* browser_context,
|
||||||
|
const GURL& url,
|
||||||
|
bool allow_credentials) {
|
||||||
|
auto* session = electron::api::Session::FromWrappedClass(
|
||||||
|
v8::Isolate::GetCurrent(),
|
||||||
|
static_cast<electron::AtomBrowserContext*>(browser_context));
|
||||||
|
if (session) {
|
||||||
|
session->Emit("preconnect", url, allow_credentials);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ElectronRenderMessageFilter::ElectronRenderMessageFilter(
|
||||||
|
content::BrowserContext* browser_context)
|
||||||
|
: BrowserMessageFilter(kRenderFilteredMessageClasses,
|
||||||
|
base::size(kRenderFilteredMessageClasses)),
|
||||||
|
browser_context_(browser_context) {}
|
||||||
|
|
||||||
|
ElectronRenderMessageFilter::~ElectronRenderMessageFilter() {}
|
||||||
|
|
||||||
|
bool ElectronRenderMessageFilter::OnMessageReceived(
|
||||||
|
const IPC::Message& message) {
|
||||||
|
bool handled = true;
|
||||||
|
IPC_BEGIN_MESSAGE_MAP(ElectronRenderMessageFilter, message)
|
||||||
|
IPC_MESSAGE_HANDLER(NetworkHintsMsg_Preconnect, OnPreconnect)
|
||||||
|
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||||
|
IPC_END_MESSAGE_MAP()
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ElectronRenderMessageFilter::OnPreconnect(int render_frame_id,
|
||||||
|
const GURL& url,
|
||||||
|
bool allow_credentials,
|
||||||
|
int count) {
|
||||||
|
if (count < 1) {
|
||||||
|
LOG(WARNING) << "NetworkHintsMsg_Preconnect IPC with invalid count: "
|
||||||
|
<< count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!url.is_valid() || !url.has_host() || !url.has_scheme() ||
|
||||||
|
!url.SchemeIsHTTPOrHTTPS()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::PostTask(FROM_HERE, {BrowserThread::UI},
|
||||||
|
base::BindOnce(&EmitPreconnect, browser_context_, url,
|
||||||
|
allow_credentials));
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace predictors {
|
||||||
|
|
||||||
|
PreconnectRequest::PreconnectRequest(
|
||||||
|
const GURL& origin,
|
||||||
|
int num_sockets,
|
||||||
|
const net::NetworkIsolationKey& network_isolation_key)
|
||||||
|
: origin(origin), num_sockets(num_sockets) {
|
||||||
|
DCHECK_GE(num_sockets, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace predictors
|
46
shell/browser/renderer_host/electron_render_message_filter.h
Normal file
46
shell/browser/renderer_host/electron_render_message_filter.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright (c) 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 SHELL_BROWSER_RENDERER_HOST_ELECTRON_RENDER_MESSAGE_FILTER_H_
|
||||||
|
#define SHELL_BROWSER_RENDERER_HOST_ELECTRON_RENDER_MESSAGE_FILTER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "content/public/browser/browser_message_filter.h"
|
||||||
|
|
||||||
|
class GURL;
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class BrowserContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace predictors {
|
||||||
|
class PreconnectManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class filters out incoming Chrome-specific IPC messages for the renderer
|
||||||
|
// process on the IPC thread.
|
||||||
|
class ElectronRenderMessageFilter : public content::BrowserMessageFilter {
|
||||||
|
public:
|
||||||
|
explicit ElectronRenderMessageFilter(
|
||||||
|
content::BrowserContext* browser_context);
|
||||||
|
|
||||||
|
// content::BrowserMessageFilter methods:
|
||||||
|
bool OnMessageReceived(const IPC::Message& message) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~ElectronRenderMessageFilter() override;
|
||||||
|
|
||||||
|
void OnPreconnect(int render_frame_id,
|
||||||
|
const GURL& url,
|
||||||
|
bool allow_credentials,
|
||||||
|
int count);
|
||||||
|
|
||||||
|
content::BrowserContext* browser_context_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ElectronRenderMessageFilter);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHELL_BROWSER_RENDERER_HOST_ELECTRON_RENDER_MESSAGE_FILTER_H_
|
|
@ -11,6 +11,7 @@
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/strings/string_split.h"
|
#include "base/strings/string_split.h"
|
||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
|
#include "components/network_hints/renderer/prescient_networking_dispatcher.h"
|
||||||
#include "content/common/buildflags.h"
|
#include "content/common/buildflags.h"
|
||||||
#include "content/public/common/content_constants.h"
|
#include "content/public/common/content_constants.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
|
@ -201,6 +202,9 @@ void RendererClientBase::RenderThreadStarted() {
|
||||||
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
|
blink::WebSecurityPolicy::RegisterURLSchemeAsAllowingServiceWorkers("file");
|
||||||
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file");
|
blink::SchemeRegistry::RegisterURLSchemeAsSupportingFetchAPI("file");
|
||||||
|
|
||||||
|
prescient_networking_dispatcher_.reset(
|
||||||
|
new network_hints::PrescientNetworkingDispatcher());
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// Set ApplicationUserModelID in renderer process.
|
// Set ApplicationUserModelID in renderer process.
|
||||||
base::string16 app_id =
|
base::string16 app_id =
|
||||||
|
@ -318,6 +322,10 @@ void RendererClientBase::DidSetUserAgent(const std::string& user_agent) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blink::WebPrescientNetworking* RendererClientBase::GetPrescientNetworking() {
|
||||||
|
return prescient_networking_dispatcher_.get();
|
||||||
|
}
|
||||||
|
|
||||||
void RendererClientBase::RunScriptsAtDocumentStart(
|
void RendererClientBase::RunScriptsAtDocumentStart(
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
#include "chrome/renderer/media/chrome_key_systems_provider.h" // nogncheck
|
#include "chrome/renderer/media/chrome_key_systems_provider.h" // nogncheck
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace network_hints {
|
||||||
|
class PrescientNetworkingDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
class ExtensionsClient;
|
class ExtensionsClient;
|
||||||
|
@ -47,6 +51,7 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||||
content::RenderFrame* render_frame,
|
content::RenderFrame* render_frame,
|
||||||
int world_id) = 0;
|
int world_id) = 0;
|
||||||
|
|
||||||
|
blink::WebPrescientNetworking* GetPrescientNetworking() override;
|
||||||
bool isolated_world() const { return isolated_world_; }
|
bool isolated_world() const { return isolated_world_; }
|
||||||
|
|
||||||
// Get the context that the Electron API is running in.
|
// Get the context that the Electron API is running in.
|
||||||
|
@ -90,10 +95,14 @@ class RendererClientBase : public content::ContentRendererClient {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<network_hints::PrescientNetworkingDispatcher>
|
||||||
|
prescient_networking_dispatcher_;
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||||
std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
|
std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
|
||||||
std::unique_ptr<AtomExtensionsRendererClient> extensions_renderer_client_;
|
std::unique_ptr<AtomExtensionsRendererClient> extensions_renderer_client_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WIDEVINE_CDM_AVAILABLE)
|
#if defined(WIDEVINE_CDM_AVAILABLE)
|
||||||
ChromeKeySystemsProvider key_systems_provider_;
|
ChromeKeySystemsProvider key_systems_provider_;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1136,6 +1136,66 @@ describe('BrowserWindow module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('preconnect feature', () => {
|
||||||
|
let w = null as unknown as BrowserWindow
|
||||||
|
|
||||||
|
let server = null as unknown as http.Server
|
||||||
|
let url = null as unknown as string
|
||||||
|
let connections = 0
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
connections = 0
|
||||||
|
server = http.createServer((req, res) => {
|
||||||
|
if (req.url === '/link') {
|
||||||
|
res.setHeader('Content-type', 'text/html')
|
||||||
|
res.end(`<head><link rel="preconnect" href="//example.com" /></head><body>foo</body>`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res.end()
|
||||||
|
})
|
||||||
|
server.on('connection', (connection) => { connections++ })
|
||||||
|
|
||||||
|
await new Promise(resolve => server.listen(0, '127.0.0.1', () => resolve()))
|
||||||
|
url = `http://127.0.0.1:${(server.address() as AddressInfo).port}`
|
||||||
|
})
|
||||||
|
afterEach(async () => {
|
||||||
|
server.close()
|
||||||
|
await closeWindow(w)
|
||||||
|
w = null as unknown as BrowserWindow
|
||||||
|
server = null as unknown as http.Server
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calling preconnect() connects to the server', (done) => {
|
||||||
|
w = new BrowserWindow({show: false})
|
||||||
|
w.webContents.on('did-start-navigation', (event, preconnectUrl, isInPlace, isMainFrame, frameProcessId, frameRoutingId) => {
|
||||||
|
w.webContents.session.preconnect({
|
||||||
|
url: preconnectUrl,
|
||||||
|
numSockets: 4
|
||||||
|
})
|
||||||
|
})
|
||||||
|
w.webContents.on('did-finish-load', () => {
|
||||||
|
expect(connections).to.equal(4)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL(url)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not preconnect unless requested', async () => {
|
||||||
|
w = new BrowserWindow({show: false})
|
||||||
|
await w.loadURL(url)
|
||||||
|
expect(connections).to.equal(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('parses <link rel=preconnect>', async () => {
|
||||||
|
w = new BrowserWindow({show: true})
|
||||||
|
const p = emittedOnce(w.webContents.session, 'preconnect')
|
||||||
|
w.loadURL(url + '/link')
|
||||||
|
const [, preconnectUrl, allowCredentials] = await p
|
||||||
|
expect(preconnectUrl).to.equal('http://example.com/')
|
||||||
|
expect(allowCredentials).to.be.true('allowCredentials')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('BrowserWindow.setAutoHideCursor(autoHide)', () => {
|
describe('BrowserWindow.setAutoHideCursor(autoHide)', () => {
|
||||||
let w = null as unknown as BrowserWindow
|
let w = null as unknown as BrowserWindow
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
Loading…
Reference in a new issue