8000 fix: webRequest module should work with file:// protocol by zcbenz · Pull Request #22903 · electron/electron · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

fix: webRequest module should work with file:// protocol #22903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions shell/browser/api/electron_api_web_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,12 @@ int WebRequest::OnHeadersReceived(
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) {
const std::string& status_line =
original_response_headers ? original_response_headers->GetStatusLine()
: std::string();
return HandleResponseEvent(
kOnHeadersReceived, info, std::move(callback),
std::make_pair(override_response_headers,
original_response_headers->GetStatusLine()),
request);
std::make_pair(override_response_headers, status_line), request);
}

void WebRequest::OnSendHeaders(extensions::WebRequestInfo* info,
Expand Down
6 changes: 4 additions & 2 deletions shell/browser/electron_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,8 @@ void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
context, false /* we don't support extensions::WebViewGuest */));
#endif
auto* protocol_registry = ProtocolRegistry::FromBrowserContext(context);
protocol_registry->RegisterURLLoaderFactories(factories);
protocol_registry->RegisterURLLoaderFactories(
URLLoaderFactoryType::kNavigation, factories);
}

#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
Expand Down Expand Up @@ -1231,7 +1232,8 @@ void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(

if (web_contents) {
ProtocolRegistry::FromBrowserContext(web_contents->GetBrowserContext())
->RegisterURLLoaderFactories(factories);
->RegisterURLLoaderFactories(URLLoaderFactoryType::kDocumentSubResource,
factories);
}
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
Expand Down
7 changes: 5 additions & 2 deletions shell/browser/net/proxying_url_loader_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -825,8 +825,11 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart(
return;
}

// Intercept file:// protocol to support asar archives.
if (request.url.SchemeIsFile()) {
// The loader of ServiceWorker forbids loading scripts from file:// URLs, and
// Chromium does not provide a way to override this behavior. So in order to
// make ServiceWorker work with file:// URLs, we have to intercept its
// requests here.
if (IsForServiceWorkerScript() && request.url.SchemeIsFile()) {
asar::CreateAsarURLLoader(request, std::move(loader), std::move(client),
new net::HttpResponseHeaders(""));
return;
Expand Down
52 changes: 52 additions & 0 deletions shell/browser/protocol_registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,46 @@
// found in the LICENSE file.

#include <memory>
#include <utility>

#include "shell/browser/electron_browser_context.h"
#include "shell/browser/net/asar/asar_url_loader.h"
#include "shell/browser/protocol_registry.h"

namespace electron {

namespace {

// Provide support for accessing asar archives in file:// protocol.
class AsarURLLoaderFactory : public network::mojom::URLLoaderFactory {
public:
AsarURLLoaderFactory() {}

private:
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(
mojo::PendingReceiver<network::mojom::URLLoader> loader,
int32_t routing_id,
int32_t request_id,
uint32_t options,
const network::ResourceRequest& request,
mojo::PendingRemote<network::mojom::URLLoaderClient> client,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
override {
asar::CreateAsarURLLoader(request, std::move(loader), std::move(client),
10000 new net::HttpResponseHeaders(""));
}

void Clone(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader) override {
receivers_.Add(this, std::move(loader));
}

mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
};

} // namespace

// static
ProtocolRegistry* ProtocolRegistry::FromBrowserContext(
content::BrowserContext* context) {
Expand All @@ -20,7 +54,25 @@ ProtocolRegistry::ProtocolRegistry() {}
ProtocolRegistry::~ProtocolRegistry() = default;

void ProtocolRegistry::RegisterURLLoaderFactories(
URLLoaderFactoryType type,
content::ContentBrowserClient::NonNetworkURLLoaderFactoryMap* factories) {
// Override the default FileURLLoaderFactory to support asar archives.
if (type == URLLoaderFactoryType::kNavigation) {
// Always allow navigating to file:// URLs.
//
// Note that Chromium calls |emplace| to create the default file factory
// after this call, so it won't override our asar factory.
DCHECK(!base::Contains(*factories, url::kFileScheme));
factories->emplace(url::kFileScheme,
std::make_unique<AsarURLLoaderFactory>());
} else if (type == URLLoaderFactoryType::kDocumentSubResource) {
// Only support requesting file:// subresource URLs when Chromium does so,
// it is usually supported under file:// or about:blank documents.
auto file_factory = factories->find(url::kFileScheme);
if (file_factory != factories->end())
file_factory->second = std::make_unique<AsarURLLoaderFactory>();
}

for (const auto& it : handlers_) {
factories->emplace(it.first, std::make_unique<ElectronURLLoaderFactory>(
it.second.first, it.second.second));
Expand Down
4 changes: 4 additions & 0 deletions shell/browser/protocol_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class ProtocolRegistry {

static ProtocolRegistry* FromBrowserContext(content::BrowserContext*);

using URLLoaderFactoryType =
content::ContentBrowserClient::URLLoaderFactoryType;

void RegisterURLLoaderFactories(
URLLoaderFactoryType type,
content::ContentBrowserClient::NonNetworkURLLoaderFactoryMap* factories);

const HandlersMap& intercept_handlers() const { return intercept_handlers_; }
Expand Down
32 changes: 32 additions & 0 deletions spec-main/api-web-request-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from 'chai';
import * as http from 'http';
import * as qs from 'querystring';
import * as path from 'path';
import * as url from 'url';
import * as WebSocket from 'ws';
import { ipcMain, protocol, session, WebContents, webContents } from 'electron';
import { AddressInfo } from 'net';
Expand Down Expand Up @@ -133,11 +134,24 @@ describe('webRequest module', () => {
await ajax(defaultURL + 'serverRedirect');
await ajax(defaultURL + 'serverRedirect');
});

it('works with file:// protocol', (done) => {
ses.webRequest.onBeforeRequest((details, callback) => {
callback({ cancel: true });
done();
});
ajax(url.format({
pathname: path.join(fixturesPath, 'blank.html').replace(/\\/g, '/'),
protocol: 'file',
slashes: true
}));
});
});

describe('webRequest.onBeforeSendHeaders', () => {
afterEach(() => {
ses.webRequest.onBeforeSendHeaders(null);
ses.webRequest.onSendHeaders(null);
});

it('receives details object', async () => {
Expand Down Expand Up @@ -192,6 +206,24 @@ describe('webRequest module', () => {
});
await ajax(defaultURL);
});

it('works with file:// protocol', (done) => {
const requestHeaders = {
Test: 'header'
};
ses.webRequest.onBeforeSendHeaders((details, callback) => {
callback({ requestHeaders: requestHeaders });
});
ses.webRequest.onSendHeaders((details) => {
expect(details.requestHeaders).to.deep.equal(requestHeaders);
done();
});
ajax(url.format({
pathname: path.join(fixturesPath, 'blank.html').replace(/\\/g, '/'),
protocol: 'file',
slashes: true
}));
});
});

describe('webRequest.onSendHeaders', () => {
Expand Down
0