Skip to content

Commit 40a212e

Browse files
authored
fix: make webRequest work with WebSocket (7-1-x) (electron#22141)
* fix: make webRequest work with WebSocket * test: install modules for spec-main
1 parent cb9b3b2 commit 40a212e

15 files changed

+906
-63
lines changed

docs/api/web-request.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ response are visible by the time this listener is fired.
146146
* `timestamp` Double
147147
* `statusLine` String
148148
* `statusCode` Integer
149+
* `requestHeaders` Record<string, string>
149150
* `responseHeaders` Record<string, string[]> (optional)
150151
* `callback` Function
151152
* `headersReceivedResponse` Object
@@ -228,6 +229,7 @@ redirect is about to occur.
228229
* `fromCache` Boolean
229230
* `statusCode` Integer
230231
* `statusLine` String
232+
* `error` String
231233

232234
The `listener` will be called with `listener(details)` when a request is
233235
completed.

filenames.gni

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ filenames = {
221221
"shell/browser/net/cert_verifier_client.h",
222222
"shell/browser/net/proxying_url_loader_factory.cc",
223223
"shell/browser/net/proxying_url_loader_factory.h",
224+
"shell/browser/net/proxying_websocket.cc",
225+
"shell/browser/net/proxying_websocket.h",
224226
"shell/browser/net/network_context_service_factory.cc",
225227
"shell/browser/net/network_context_service_factory.h",
226228
"shell/browser/net/network_context_service.cc",
@@ -233,6 +235,7 @@ filenames = {
233235
"shell/browser/net/system_network_context_manager.h",
234236
"shell/browser/net/url_pipe_loader.cc",
235237
"shell/browser/net/url_pipe_loader.h",
238+
"shell/browser/net/web_request_api_interface.h",
236239
"shell/browser/notifications/linux/libnotify_notification.cc",
237240
"shell/browser/notifications/linux/libnotify_notification.h",
238241
"shell/browser/notifications/linux/notification_presenter_linux.cc",

script/spec-runner.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ async function main () {
4545
(lastSpecInstallHash !== currentSpecInstallHash)
4646

4747
if (somethingChanged) {
48-
await installSpecModules()
48+
await installSpecModules(path.resolve(__dirname, '..', 'spec'))
49+
await installSpecModules(path.resolve(__dirname, '..', 'spec-main'))
4950
await getSpecHash().then(saveSpecHash)
5051
}
5152

@@ -140,19 +141,20 @@ async function runMainProcessElectronTests () {
140141
}
141142
}
142143

143-
async function installSpecModules () {
144+
async function installSpecModules (dir) {
144145
const nodeDir = path.resolve(BASE, `out/${utils.OUT_DIR}/gen/node_headers`)
145146
const env = Object.assign({}, process.env, {
146147
npm_config_nodedir: nodeDir,
147148
npm_config_msvs_version: '2017'
148149
})
149150
const { status } = childProcess.spawnSync(NPX_CMD, [`yarn@${YARN_VERSION}`, 'install', '--frozen-lockfile'], {
150151
env,
151-
cwd: path.resolve(__dirname, '../spec'),
152+
cwd: dir,
152153
stdio: 'inherit'
153154
})
154155
if (status !== 0 && !process.env.IGNORE_YARN_INSTALL_ERROR) {
155-
throw new Error('Failed to yarn install in the spec folder')
156+
console.log(`Failed to yarn install in '${dir}'`)
157+
process.exit(1)
156158
}
157159
}
158160

@@ -161,7 +163,9 @@ function getSpecHash () {
161163
(async () => {
162164
const hasher = crypto.createHash('SHA256')
163165
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec/package.json')))
166+
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec-main/package.json')))
164167
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec/yarn.lock')))
168+
hasher.update(fs.readFileSync(path.resolve(__dirname, '../spec-main/yarn.lock')))
165169
return hasher.digest('hex')
166170
})(),
167171
(async () => {

shell/browser/api/atom_api_web_request_ns.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#include "gin/wrappable.h"
1616
#include "native_mate/dictionary.h"
1717
#include "native_mate/handle.h"
18-
#include "shell/browser/net/proxying_url_loader_factory.h"
18+
#include "shell/browser/net/web_request_api_interface.h"
1919

2020
namespace content {
2121
class BrowserContext;
@@ -52,10 +52,6 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS>, public WebRequestAPI {
5252
v8::Isolate* isolate) override;
5353
const char* GetTypeName() override;
5454

55-
private:
56-
WebRequestNS(v8::Isolate* isolate, content::BrowserContext* browser_context);
57-
~WebRequestNS() override;
58-
5955
// WebRequestAPI:
6056
bool HasListener() const override;
6157
int OnBeforeRequest(extensions::WebRequestInfo* info,
@@ -89,6 +85,10 @@ class WebRequestNS : public gin::Wrappable<WebRequestNS>, public WebRequestAPI {
8985
int net_error) override;
9086
void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) override;
9187

88+
private:
89+
WebRequestNS(v8::Isolate* isolate, content::BrowserContext* browser_context);
90+
~WebRequestNS() override;
91+
9292
enum SimpleEvent {
9393
kOnSendHeaders,
9494
kOnBeforeRedirect,

shell/browser/atom_browser_client.cc

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
#include "shell/browser/net/network_context_service.h"
6868
#include "shell/browser/net/network_context_service_factory.h"
6969
#include "shell/browser/net/proxying_url_loader_factory.h"
70+
#include "shell/browser/net/proxying_websocket.h"
7071
#include "shell/browser/net/system_network_context_manager.h"
7172
#include "shell/browser/notifications/notification_presenter.h"
7273
#include "shell/browser/notifications/platform_notification_service.h"
@@ -982,6 +983,42 @@ void AtomBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
982983
}
983984
}
984985

986+
bool AtomBrowserClient::WillInterceptWebSocket(
987+
content::RenderFrameHost* frame) {
988+
if (!frame)
989+
return false;
990+
991+
v8::Isolate* isolate = v8::Isolate::GetCurrent();
992+
auto* browser_context = frame->GetProcess()->GetBrowserContext();
993+
auto web_request = api::WebRequestNS::FromOrCreate(isolate, browser_context);
994+
995+
// NOTE: Some unit test environments do not initialize
996+
// BrowserContextKeyedAPI factories for e.g. WebRequest.
997+
if (!web_request.get())
998+
return false;
999+
1000+
return web_request->HasListener();
1001+
}
1002+
1003+
void AtomBrowserClient::CreateWebSocket(
1004+
content::RenderFrameHost* frame,
1005+
WebSocketFactory factory,
1006+
const GURL& url,
1007+
const GURL& site_for_cookies,
1008+
const base::Optional<std::string>& user_agent,
1009+
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
1010+
handshake_client) {
1011+
v8::Isolate* isolate = v8::Isolate::GetCurrent();
1012+
auto* browser_context = frame->GetProcess()->GetBrowserContext();
1013+
auto web_request = api::WebRequestNS::FromOrCreate(isolate, browser_context);
1014+
DCHECK(web_request.get());
1015+
ProxyingWebSocket::StartProxying(
1016+
web_request.get(), std::move(factory), url, site_for_cookies, user_agent,
1017+
std::move(handshake_client), true, frame->GetProcess()->GetID(),
1018+
frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
1019+
&next_id_);
1020+
}
1021+
9851022
bool AtomBrowserClient::WillCreateURLLoaderFactory(
9861023
content::BrowserContext* browser_context,
9871024
content::RenderFrameHost* frame_host,
@@ -1010,7 +1047,7 @@ bool AtomBrowserClient::WillCreateURLLoaderFactory(
10101047

10111048
new ProxyingURLLoaderFactory(
10121049
web_request.get(), protocol->intercept_handlers(), render_process_id,
1013-
std::move(proxied_receiver), std::move(target_factory_info),
1050+
&next_id_, std::move(proxied_receiver), std::move(target_factory_info),
10141051
std::move(header_client_receiver), type);
10151052

10161053
if (bypass_redirect_checks)

shell/browser/atom_browser_client.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,15 @@ class AtomBrowserClient : public content::ContentBrowserClient,
170170
int render_process_id,
171171
int render_frame_id,
172172
NonNetworkURLLoaderFactoryMap* factories) override;
173+
void CreateWebSocket(
174+
content::RenderFrameHost* frame,
175+
WebSocketFactory factory,
176+
const GURL& url,
177+
const GURL& site_for_cookies,
178+
const base::Optional<std::string>& user_agent,
179+
mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
180+
handshake_client) override;
181+
bool WillInterceptWebSocket(content::RenderFrameHost*) override;
173182
bool WillCreateURLLoaderFactory(
174183
content::BrowserContext* browser_context,
175184
content::RenderFrameHost* frame,
@@ -274,6 +283,10 @@ class AtomBrowserClient : public content::ContentBrowserClient,
274283

275284
bool disable_process_restart_tricks_ = false;
276285

286+
// Simple shared ID generator, used by ProxyingURLLoaderFactory and
287+
// ProxyingWebSocket classes.
288+
uint64_t next_id_ = 0;
289+
277290
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
278291
};
279292

shell/browser/net/proxying_url_loader_factory.cc

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,6 @@
1818
#include "shell/common/options_switches.h"
1919

2020
namespace electron {
21-
22-
namespace {
23-
24-
int64_t g_request_id = 0;
25-
26-
} // namespace
27-
2821
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
2922
FollowRedirectParams() = default;
3023
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams::
@@ -668,6 +661,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
668661
WebRequestAPI* web_request_api,
669662
const HandlersMap& intercepted_handlers,
670663
int render_process_id,
664+
uint64_t* request_id_generator,
671665
network::mojom::URLLoaderFactoryRequest loader_request,
672666
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
673667
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
@@ -676,6 +670,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory(
676670
: web_request_api_(web_request_api),
677671
intercepted_handlers_(intercepted_handlers),
678672
render_process_id_(render_process_id),
673+
request_id_generator_(request_id_generator),
679674
loader_factory_type_(loader_factory_type) {
680675
target_factory_.Bind(std::move(target_factory_info));
681676
target_factory_.set_connection_error_handler(base::BindOnce(
@@ -751,7 +746,7 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
751746
// per-BrowserContext so extensions can make sense of it. Note that
752747
// |network_service_request_id_| by contrast is not necessarily unique, so we
753748
// don't use it for identity here.
754-
const uint64_t web_request_id = ++g_request_id;
749+
const uint64_t web_request_id = ++(*request_id_generator_);
755750

756751
// Notes: Chromium assumes that requests with zero-ID would never use the
757752
// "extraHeaders" code path, however in Electron requests started from

shell/browser/net/proxying_url_loader_factory.h

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,52 +20,10 @@
2020
#include "services/network/public/mojom/network_context.mojom.h"
2121
#include "services/network/public/mojom/url_loader.mojom.h"
2222
#include "shell/browser/net/atom_url_loader_factory.h"
23+
#include "shell/browser/net/web_request_api_interface.h"
2324

2425
namespace electron {
2526

26-
// Defines the interface for WebRequest API, implemented by api::WebRequestNS.
27-
class WebRequestAPI {
28-
public:
29-
virtual ~WebRequestAPI() {}
30-
31-
using BeforeSendHeadersCallback =
32-
base::OnceCallback<void(const std::set<std::string>& removed_headers,
33-
const std::set<std::string>& set_headers,
34-
int error_code)>;
35-
36-
virtual bool HasListener() const = 0;
37-
virtual int OnBeforeRequest(extensions::WebRequestInfo* info,
38-
const network::ResourceRequest& request,
39-
net::CompletionOnceCallback callback,
40-
GURL* new_url) = 0;
41-
virtual int OnBeforeSendHeaders(extensions::WebRequestInfo* info,
42-
const network::ResourceRequest& request,
43-
BeforeSendHeadersCallback callback,
44-
net::HttpRequestHeaders* headers) = 0;
45-
virtual int OnHeadersReceived(
46-
extensions::WebRequestInfo* info,
47-
const network::ResourceRequest& request,
48-
net::CompletionOnceCallback callback,
49-
const net::HttpResponseHeaders* original_response_headers,
50-
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
51-
GURL* allowed_unsafe_redirect_url) = 0;
52-
virtual void OnSendHeaders(extensions::WebRequestInfo* info,
53-
const network::ResourceRequest& request,
54-
const net::HttpRequestHeaders& headers) = 0;
55-
virtual void OnBeforeRedirect(extensions::WebRequestInfo* info,
56-
const network::ResourceRequest& request,
57-
const GURL& new_location) = 0;
58-
virtual void OnResponseStarted(extensions::WebRequestInfo* info,
59-
const network::ResourceRequest& request) = 0;
60-
virtual void OnErrorOccurred(extensions::WebRequestInfo* info,
61-
const network::ResourceRequest& request,
62-
int net_error) = 0;
63-
virtual void OnCompleted(extensions::WebRequestInfo* info,
64-
const network::ResourceRequest& request,
65-
int net_error) = 0;
66-
virtual void OnRequestWillBeDestroyed(extensions::WebRequestInfo* info) = 0;
67-
};
68-
6927
// This class is responsible for following tasks when NetworkService is enabled:
7028
// 1. handling intercepted protocols;
7129
// 2. implementing webRequest module;
@@ -203,6 +161,7 @@ class ProxyingURLLoaderFactory
203161
WebRequestAPI* web_request_api,
204162
const HandlersMap& intercepted_handlers,
205163
int render_process_id,
164+
uint64_t* request_id_generator,
206165
network::mojom::URLLoaderFactoryRequest loader_request,
207166
network::mojom::URLLoaderFactoryPtrInfo target_factory_info,
208167
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
@@ -254,6 +213,7 @@ class ProxyingURLLoaderFactory
254213
const int render_process_id_;
255214
mojo::BindingSet<network::mojom::URLLoaderFactory> proxy_bindings_;
256215
network::mojom::URLLoaderFactoryPtr target_factory_;
216+
uint64_t* request_id_generator_; // managed by AtomBrowserClient
257217
mojo::Receiver<network::mojom::TrustedURLLoaderHeaderClient>
258218
url_loader_header_client_receiver_{this};
259219
const content::ContentBrowserClient::URLLoaderFactoryType

0 commit comments

Comments
 (0)