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
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "shell/browser/api/atom_api_session.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -594,6 +595,42 @@ v8::Local<v8::Value> Session::NetLog(v8::Isolate* isolate) {
|
|||
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
|
||||
mate::Handle<Session> Session::CreateFrom(v8::Isolate* isolate,
|
||||
AtomBrowserContext* browser_context) {
|
||||
|
@ -664,6 +701,7 @@ void Session::BuildPrototype(v8::Isolate* isolate,
|
|||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
.SetMethod("loadChromeExtension", &Session::LoadChromeExtension)
|
||||
#endif
|
||||
.SetMethod("preconnect", &Session::Preconnect)
|
||||
.SetProperty("cookies", &Session::Cookies)
|
||||
.SetProperty("netLog", &Session::NetLog)
|
||||
.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> WebRequest(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)
|
||||
void LoadChromeExtension(const base::FilePath extension_path);
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "shell/app/manifests.h"
|
||||
#include "shell/browser/api/atom_api_app.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_request_ns.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/notifications/notification_presenter.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/ui/devtools_manager_delegate.h"
|
||||
#include "shell/browser/web_contents_permission_helper.h"
|
||||
|
@ -365,6 +367,9 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
|||
prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
|
||||
true /* default value */);
|
||||
}
|
||||
|
||||
host->AddFilter(new ElectronRenderMessageFilter(host->GetBrowserContext()));
|
||||
|
||||
AddProcessPreferences(host->GetID(), prefs);
|
||||
// ensure the ProcessPreferences is removed later
|
||||
host->AddObserver(this);
|
||||
|
|
|
@ -264,6 +264,13 @@ AtomBlobReader* AtomBrowserContext::GetBlobReader() {
|
|||
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() {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "base/memory/ref_counted_delete_on_sequence.h"
|
||||
#include "base/memory/weak_ptr.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/resource_context.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
|
@ -87,6 +88,8 @@ class AtomBrowserContext
|
|||
AtomBlobReader* GetBlobReader();
|
||||
ResolveProxyHelper* GetResolveProxyHelper();
|
||||
|
||||
predictors::PreconnectManager* GetPreconnectManager();
|
||||
|
||||
// content::BrowserContext:
|
||||
base::FilePath GetPath() override;
|
||||
bool IsOffTheRecord() override;
|
||||
|
@ -164,6 +167,8 @@ class AtomBrowserContext
|
|||
// ProxyConfigClient.
|
||||
std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_;
|
||||
|
||||
std::unique_ptr<predictors::PreconnectManager> preconnect_manager_;
|
||||
|
||||
std::string user_agent_;
|
||||
base::FilePath path_;
|
||||
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_
|
Loading…
Add table
Add a link
Reference in a new issue