docs: move protocol-ns to protocol.md (#23883)
* docs: move protocol-ns to protocol.md * chore: fix up tests and implement missing pieces required for tests
This commit is contained in:
parent
edc5050a2e
commit
d3fa5ed1e8
13 changed files with 285 additions and 733 deletions
|
@ -1,309 +0,0 @@
|
||||||
# protocol (NetworkService) (Draft)
|
|
||||||
|
|
||||||
This document describes the new protocol APIs based on the [NetworkService](https://www.chromium.org/servicification).
|
|
||||||
|
|
||||||
We don't currently have an estimate of when we will enable the `NetworkService` by
|
|
||||||
default in Electron, but as Chromium is already removing non-`NetworkService`
|
|
||||||
code, we will probably switch before Electron 10.
|
|
||||||
|
|
||||||
The content of this document should be moved to `protocol.md` after we have
|
|
||||||
enabled the `NetworkService` by default in Electron.
|
|
||||||
|
|
||||||
> Register a custom protocol and intercept existing protocol requests.
|
|
||||||
|
|
||||||
Process: [Main](../glossary.md#main-process)
|
|
||||||
|
|
||||||
An example of implementing a protocol that has the same effect as the
|
|
||||||
`file://` protocol:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const { app, protocol } = require('electron')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
|
||||||
const url = request.url.substr(7)
|
|
||||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** All methods unless specified can only be used after the `ready` event
|
|
||||||
of the `app` module gets emitted.
|
|
||||||
|
|
||||||
## Using `protocol` with a custom `partition` or `session`
|
|
||||||
|
|
||||||
A protocol is registered to a specific Electron [`session`](./session.md)
|
|
||||||
object. If you don't specify a session, then your `protocol` will be applied to
|
|
||||||
the default session that Electron uses. However, if you define a `partition` or
|
|
||||||
`session` on your `browserWindow`'s `webPreferences`, then that window will use
|
|
||||||
a different session and your custom protocol will not work if you just use
|
|
||||||
`electron.protocol.XXX`.
|
|
||||||
|
|
||||||
To have your custom protocol work in combination with a custom session, you need
|
|
||||||
to register it to that session explicitly.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const { session, app, protocol } = require('electron')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
app.whenReady().then(() => {
|
|
||||||
const partition = 'persist:example'
|
|
||||||
const ses = session.fromPartition(partition)
|
|
||||||
|
|
||||||
ses.protocol.registerFileProtocol('atom', (request, callback) => {
|
|
||||||
const url = request.url.substr(7)
|
|
||||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
## Methods
|
|
||||||
|
|
||||||
The `protocol` module has the following methods:
|
|
||||||
|
|
||||||
### `protocol.registerSchemesAsPrivileged(customSchemes)`
|
|
||||||
|
|
||||||
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
|
|
||||||
|
|
||||||
**Note:** This method can only be used before the `ready` event of the `app`
|
|
||||||
module gets emitted and can be called only once.
|
|
||||||
|
|
||||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
|
||||||
resources, allows registering ServiceWorker and supports fetch API. Specify a
|
|
||||||
privilege with the value of `true` to enable the capability.
|
|
||||||
|
|
||||||
An example of registering a privileged scheme, that bypasses Content Security
|
|
||||||
Policy:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const { protocol } = require('electron')
|
|
||||||
protocol.registerSchemesAsPrivileged([
|
|
||||||
{ scheme: 'foo', privileges: { bypassCSP: true } }
|
|
||||||
])
|
|
||||||
```
|
|
||||||
|
|
||||||
A standard scheme adheres to what RFC 3986 calls [generic URI
|
|
||||||
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
|
||||||
`https` are standard schemes, while `file` is not.
|
|
||||||
|
|
||||||
Registering a scheme as standard allows relative and absolute resources to
|
|
||||||
be resolved correctly when served. Otherwise the scheme will behave like the
|
|
||||||
`file` protocol, but without the ability to resolve relative URLs.
|
|
||||||
|
|
||||||
For example when you load following page with custom protocol without
|
|
||||||
registering it as standard scheme, the image will not be loaded because
|
|
||||||
non-standard schemes can not recognize relative URLs:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<body>
|
|
||||||
<img src='test.png'>
|
|
||||||
</body>
|
|
||||||
```
|
|
||||||
|
|
||||||
Registering a scheme as standard will allow access to files through the
|
|
||||||
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
|
|
||||||
error for the scheme.
|
|
||||||
|
|
||||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
|
|
||||||
cookies) are disabled for non standard schemes. So in general if you want to
|
|
||||||
register a custom protocol to replace the `http` protocol, you have to register
|
|
||||||
it as a standard scheme.
|
|
||||||
|
|
||||||
### `protocol.registerFileProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a file as the response. The
|
|
||||||
`handler` will be called with `request` and `callback` where `request` is
|
|
||||||
an incoming request for the `scheme`.
|
|
||||||
|
|
||||||
To handle the `request`, the `callback` should be called with either the file's
|
|
||||||
path or an object that has a `path` property, e.g. `callback(filePath)` or
|
|
||||||
`callback({ path: filePath })`. The `filePath` must be an absolute path.
|
|
||||||
|
|
||||||
By default the `scheme` is treated like `http:`, which is parsed differently
|
|
||||||
from protocols that follow the "generic URI syntax" like `file:`.
|
|
||||||
|
|
||||||
### `protocol.registerBufferProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a `Buffer` as a response.
|
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
|
||||||
should be called with either a `Buffer` object or an object that has the `data`
|
|
||||||
property.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
protocol.registerBufferProtocol('atom', (request, callback) => {
|
|
||||||
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### `protocol.registerStringProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a `String` as a response.
|
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
|
||||||
should be called with either a `String` or an object that has the `data`
|
|
||||||
property.
|
|
||||||
|
|
||||||
### `protocol.registerHttpProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` ProtocolResponse
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send an HTTP request as a response.
|
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
|
||||||
should be called with an object that has the `url` property.
|
|
||||||
|
|
||||||
### `protocol.registerStreamProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a stream as a response.
|
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the
|
|
||||||
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
|
|
||||||
has the `data` property.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const { protocol } = require('electron')
|
|
||||||
const { PassThrough } = require('stream')
|
|
||||||
|
|
||||||
function createStream (text) {
|
|
||||||
const rv = new PassThrough() // PassThrough is also a Readable stream
|
|
||||||
rv.push(text)
|
|
||||||
rv.push(null)
|
|
||||||
return rv
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
|
||||||
callback({
|
|
||||||
statusCode: 200,
|
|
||||||
headers: {
|
|
||||||
'content-type': 'text/html'
|
|
||||||
},
|
|
||||||
data: createStream('<h5>Response</h5>')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
It is possible to pass any object that implements the readable stream API (emits
|
|
||||||
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
|
||||||
callback(fs.createReadStream('index.html'))
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### `protocol.unregisterProtocol(scheme)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
|
|
||||||
Unregisters the custom protocol of `scheme`.
|
|
||||||
|
|
||||||
### `protocol.isProtocolRegistered(scheme)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
|
|
||||||
Returns `Boolean` - Whether `scheme` is already registered.
|
|
||||||
|
|
||||||
### `protocol.interceptFileProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
|
||||||
which sends a file as a response.
|
|
||||||
|
|
||||||
### `protocol.interceptStringProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
|
||||||
which sends a `String` as a response.
|
|
||||||
|
|
||||||
### `protocol.interceptBufferProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
|
||||||
which sends a `Buffer` as a response.
|
|
||||||
|
|
||||||
### `protocol.interceptHttpProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` ProtocolResponse
|
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
|
||||||
which sends a new HTTP request as a response.
|
|
||||||
|
|
||||||
### `protocol.interceptStreamProtocol(scheme, handler)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
* `handler` Function
|
|
||||||
* `request` ProtocolRequest
|
|
||||||
* `callback` Function
|
|
||||||
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
|
||||||
|
|
||||||
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
|
|
||||||
protocol handler.
|
|
||||||
|
|
||||||
### `protocol.uninterceptProtocol(scheme)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
|
|
||||||
Remove the interceptor installed for `scheme` and restore its original handler.
|
|
||||||
|
|
||||||
### `protocol.isProtocolIntercepted(scheme)`
|
|
||||||
|
|
||||||
* `scheme` String
|
|
||||||
|
|
||||||
Returns `Boolean` - Whether `scheme` is already intercepted.
|
|
||||||
|
|
||||||
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
|
|
|
@ -15,8 +15,6 @@ app.whenReady().then(() => {
|
||||||
protocol.registerFileProtocol('atom', (request, callback) => {
|
protocol.registerFileProtocol('atom', (request, callback) => {
|
||||||
const url = request.url.substr(7)
|
const url = request.url.substr(7)
|
||||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -26,9 +24,15 @@ of the `app` module gets emitted.
|
||||||
|
|
||||||
## Using `protocol` with a custom `partition` or `session`
|
## Using `protocol` with a custom `partition` or `session`
|
||||||
|
|
||||||
A protocol is registered to a specific Electron [`session`](./session.md) object. If you don't specify a session, then your `protocol` will be applied to the default session that Electron uses. However, if you define a `partition` or `session` on your `browserWindow`'s `webPreferences`, then that window will use a different session and your custom protocol will not work if you just use `electron.protocol.XXX`.
|
A protocol is registered to a specific Electron [`session`](./session.md)
|
||||||
|
object. If you don't specify a session, then your `protocol` will be applied to
|
||||||
|
the default session that Electron uses. However, if you define a `partition` or
|
||||||
|
`session` on your `browserWindow`'s `webPreferences`, then that window will use
|
||||||
|
a different session and your custom protocol will not work if you just use
|
||||||
|
`electron.protocol.XXX`.
|
||||||
|
|
||||||
To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.
|
To have your custom protocol work in combination with a custom session, you need
|
||||||
|
to register it to that session explicitly.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { session, app, protocol } = require('electron')
|
const { session, app, protocol } = require('electron')
|
||||||
|
@ -41,17 +45,9 @@ app.whenReady().then(() => {
|
||||||
ses.protocol.registerFileProtocol('atom', (request, callback) => {
|
ses.protocol.registerFileProtocol('atom', (request, callback) => {
|
||||||
const url = request.url.substr(7)
|
const url = request.url.substr(7)
|
||||||
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
callback({ path: path.normalize(`${__dirname}/${url}`) })
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
mainWindow = new BrowserWindow({
|
mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
||||||
width: 800,
|
|
||||||
height: 600,
|
|
||||||
webPreferences: {
|
|
||||||
partition: partition
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -63,15 +59,15 @@ The `protocol` module has the following methods:
|
||||||
|
|
||||||
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
|
* `customSchemes` [CustomScheme[]](structures/custom-scheme.md)
|
||||||
|
|
||||||
|
|
||||||
**Note:** This method can only be used before the `ready` event of the `app`
|
**Note:** This method can only be used before the `ready` event of the `app`
|
||||||
module gets emitted and can be called only once.
|
module gets emitted and can be called only once.
|
||||||
|
|
||||||
Registers the `scheme` as standard, secure, bypasses content security policy for resources,
|
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||||
allows registering ServiceWorker and supports fetch API.
|
resources, allows registering ServiceWorker and supports fetch API. Specify a
|
||||||
|
privilege with the value of `true` to enable the capability.
|
||||||
|
|
||||||
Specify a privilege with the value of `true` to enable the capability.
|
An example of registering a privileged scheme, that bypasses Content Security
|
||||||
An example of registering a privileged scheme, with bypassing Content Security Policy:
|
Policy:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { protocol } = require('electron')
|
const { protocol } = require('electron')
|
||||||
|
@ -84,7 +80,7 @@ A standard scheme adheres to what RFC 3986 calls [generic URI
|
||||||
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and
|
||||||
`https` are standard schemes, while `file` is not.
|
`https` are standard schemes, while `file` is not.
|
||||||
|
|
||||||
Registering a scheme as standard, will allow relative and absolute resources to
|
Registering a scheme as standard allows relative and absolute resources to
|
||||||
be resolved correctly when served. Otherwise the scheme will behave like the
|
be resolved correctly when served. Otherwise the scheme will behave like the
|
||||||
`file` protocol, but without the ability to resolve relative URLs.
|
`file` protocol, but without the ability to resolve relative URLs.
|
||||||
|
|
||||||
|
@ -102,168 +98,102 @@ Registering a scheme as standard will allow access to files through the
|
||||||
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
|
[FileSystem API][file-system-api]. Otherwise the renderer will throw a security
|
||||||
error for the scheme.
|
error for the scheme.
|
||||||
|
|
||||||
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies)
|
By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB,
|
||||||
are disabled for non standard schemes. So in general if you want to register a
|
cookies) are disabled for non standard schemes. So in general if you want to
|
||||||
custom protocol to replace the `http` protocol, you have to register it as a standard scheme.
|
register a custom protocol to replace the `http` protocol, you have to register
|
||||||
|
it as a standard scheme.
|
||||||
|
|
||||||
`protocol.registerSchemesAsPrivileged` can be used to replicate the functionality of the previous `protocol.registerStandardSchemes`, `webFrame.registerURLSchemeAs*` and `protocol.registerServiceWorkerSchemes` functions that existed prior to Electron 5.0.0, for example:
|
### `protocol.registerFileProtocol(scheme, handler)`
|
||||||
|
|
||||||
**before (<= v4.x)**
|
|
||||||
```javascript
|
|
||||||
// Main
|
|
||||||
protocol.registerStandardSchemes(['scheme1', 'scheme2'], { secure: true })
|
|
||||||
// Renderer
|
|
||||||
webFrame.registerURLSchemeAsPrivileged('scheme1', { secure: true })
|
|
||||||
webFrame.registerURLSchemeAsPrivileged('scheme2', { secure: true })
|
|
||||||
```
|
|
||||||
|
|
||||||
**after (>= v5.x)**
|
|
||||||
```javascript
|
|
||||||
protocol.registerSchemesAsPrivileged([
|
|
||||||
{ scheme: 'scheme1', privileges: { standard: true, secure: true } },
|
|
||||||
{ scheme: 'scheme2', privileges: { standard: true, secure: true } }
|
|
||||||
])
|
|
||||||
```
|
|
||||||
|
|
||||||
### `protocol.registerFileProtocol(scheme, handler[, completion])`
|
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `filePath` String | [FilePathWithHeaders](structures/file-path-with-headers.md) (optional)
|
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send the file as a response. The
|
Returns `Boolean` - Whether the protocol was successfully registered
|
||||||
`handler` will be called with `handler(request, callback)` when a `request` is
|
|
||||||
going to be created with `scheme`. `completion` will be called with
|
Registers a protocol of `scheme` that will send a file as the response. The
|
||||||
`completion(null)` when `scheme` is successfully registered or
|
`handler` will be called with `request` and `callback` where `request` is
|
||||||
`completion(error)` when failed.
|
an incoming request for the `scheme`.
|
||||||
|
|
||||||
To handle the `request`, the `callback` should be called with either the file's
|
To handle the `request`, the `callback` should be called with either the file's
|
||||||
path or an object that has a `path` property, e.g. `callback(filePath)` or
|
path or an object that has a `path` property, e.g. `callback(filePath)` or
|
||||||
`callback({ path: filePath })`. The object may also have a `headers` property
|
`callback({ path: filePath })`. The `filePath` must be an absolute path.
|
||||||
which gives a map of headers to values for the response headers, e.g.
|
|
||||||
`callback({ path: filePath, headers: {"Content-Security-Policy": "default-src 'none'"]})`.
|
|
||||||
|
|
||||||
When `callback` is called with nothing, a number, or an object that has an
|
|
||||||
`error` property, the `request` will fail with the `error` number you
|
|
||||||
specified. For the available error numbers you can use, please see the
|
|
||||||
[net error list][net-error].
|
|
||||||
|
|
||||||
By default the `scheme` is treated like `http:`, which is parsed differently
|
By default the `scheme` is treated like `http:`, which is parsed differently
|
||||||
than protocols that follow the "generic URI syntax" like `file:`.
|
from protocols that follow the "generic URI syntax" like `file:`.
|
||||||
|
|
||||||
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
|
### `protocol.registerBufferProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `buffer` (Buffer | [MimeTypedBuffer](structures/mime-typed-buffer.md)) (optional)
|
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully registered
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a `Buffer` as a response.
|
Registers a protocol of `scheme` that will send a `Buffer` as a response.
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||||
should be called with either a `Buffer` object or an object that has the `data`,
|
should be called with either a `Buffer` object or an object that has the `data`
|
||||||
`mimeType`, and `charset` properties.
|
property.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { protocol } = require('electron')
|
|
||||||
|
|
||||||
protocol.registerBufferProtocol('atom', (request, callback) => {
|
protocol.registerBufferProtocol('atom', (request, callback) => {
|
||||||
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### `protocol.registerStringProtocol(scheme, handler[, completion])`
|
### `protocol.registerStringProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
|
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully registered
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a `String` as a response.
|
Registers a protocol of `scheme` that will send a `String` as a response.
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||||
should be called with either a `String` or an object that has the `data`,
|
should be called with either a `String` or an object that has the `data`
|
||||||
`mimeType`, and `charset` properties.
|
property.
|
||||||
|
|
||||||
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
|
### `protocol.registerHttpProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `redirectRequest` Object
|
* `response` ProtocolResponse
|
||||||
* `url` String
|
|
||||||
* `method` String (optional)
|
Returns `Boolean` - Whether the protocol was successfully registered
|
||||||
* `session` Session | null (optional)
|
|
||||||
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
|
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send an HTTP request as a response.
|
Registers a protocol of `scheme` that will send an HTTP request as a response.
|
||||||
|
|
||||||
The usage is the same with `registerFileProtocol`, except that the `callback`
|
The usage is the same with `registerFileProtocol`, except that the `callback`
|
||||||
should be called with a `redirectRequest` object that has the `url`, `method`,
|
should be called with an object that has the `url` property.
|
||||||
`referrer`, `uploadData` and `session` properties.
|
|
||||||
|
|
||||||
By default the HTTP request will reuse the current session. If you want the
|
### `protocol.registerStreamProtocol(scheme, handler)`
|
||||||
request to have a different session you should set `session` to `null`.
|
|
||||||
|
|
||||||
For POST requests the `uploadData` object must be provided.
|
|
||||||
|
|
||||||
### `protocol.registerStreamProtocol(scheme, handler[, completion])`
|
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
|
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
|
||||||
|
|
||||||
Registers a protocol of `scheme` that will send a `Readable` as a response.
|
Returns `Boolean` - Whether the protocol was successfully registered
|
||||||
|
|
||||||
The usage is similar to the other `register{Any}Protocol`, except that the
|
Registers a protocol of `scheme` that will send a stream as a response.
|
||||||
`callback` should be called with either a `Readable` object or an object that
|
|
||||||
has the `data`, `statusCode`, and `headers` properties.
|
The usage is the same with `registerFileProtocol`, except that the
|
||||||
|
`callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that
|
||||||
|
has the `data` property.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -286,8 +216,6 @@ protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||||
},
|
},
|
||||||
data: createStream('<h5>Response</h5>')
|
data: createStream('<h5>Response</h5>')
|
||||||
})
|
})
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -295,132 +223,102 @@ It is possible to pass any object that implements the readable stream API (emits
|
||||||
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
`data`/`end`/`error` events). For example, here's how a file could be returned:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const { protocol } = require('electron')
|
|
||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
protocol.registerStreamProtocol('atom', (request, callback) => {
|
protocol.registerStreamProtocol('atom', (request, callback) => {
|
||||||
callback(fs.createReadStream('index.html'))
|
callback(fs.createReadStream('index.html'))
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### `protocol.unregisterProtocol(scheme[, completion])`
|
### `protocol.unregisterProtocol(scheme)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully unregistered
|
||||||
|
|
||||||
Unregisters the custom protocol of `scheme`.
|
Unregisters the custom protocol of `scheme`.
|
||||||
|
|
||||||
### `protocol.isProtocolHandled(scheme)`
|
### `protocol.isProtocolRegistered(scheme)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
|
|
||||||
Returns `Promise<Boolean>` - fulfilled with a boolean that indicates whether there is
|
Returns `Boolean` - Whether `scheme` is already registered.
|
||||||
already a handler for `scheme`.
|
|
||||||
|
|
||||||
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
|
### `protocol.interceptFileProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `filePath` String
|
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||||
which sends a file as a response.
|
which sends a file as a response.
|
||||||
|
|
||||||
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
|
### `protocol.interceptStringProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `data` (String | [StringProtocolResponse](structures/string-protocol-response.md)) (optional)
|
* `response` (String | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||||
which sends a `String` as a response.
|
which sends a `String` as a response.
|
||||||
|
|
||||||
### `protocol.interceptBufferProtocol(scheme, handler[, completion])`
|
### `protocol.interceptBufferProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `buffer` Buffer (optional)
|
* `response` (Buffer | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||||
which sends a `Buffer` as a response.
|
which sends a `Buffer` as a response.
|
||||||
|
|
||||||
### `protocol.interceptHttpProtocol(scheme, handler[, completion])`
|
### `protocol.interceptHttpProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `redirectRequest` Object
|
* `response` [ProtocolResponse](structures/protocol-response.md)
|
||||||
* `url` String
|
|
||||||
* `method` String (optional)
|
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||||
* `session` Session | null (optional)
|
|
||||||
* `uploadData` [ProtocolResponseUploadData](structures/protocol-response-upload-data.md) (optional)
|
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
|
||||||
|
|
||||||
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
Intercepts `scheme` protocol and uses `handler` as the protocol's new handler
|
||||||
which sends a new HTTP request as a response.
|
which sends a new HTTP request as a response.
|
||||||
|
|
||||||
### `protocol.interceptStreamProtocol(scheme, handler[, completion])`
|
### `protocol.interceptStreamProtocol(scheme, handler)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `handler` Function
|
* `handler` Function
|
||||||
* `request` Object
|
* `request` ProtocolRequest
|
||||||
* `url` String
|
|
||||||
* `headers` Record<String, String>
|
|
||||||
* `referrer` String
|
|
||||||
* `method` String
|
|
||||||
* `uploadData` [UploadData[]](structures/upload-data.md)
|
|
||||||
* `callback` Function
|
* `callback` Function
|
||||||
* `stream` (ReadableStream | [StreamProtocolResponse](structures/stream-protocol-response.md)) (optional)
|
* `response` (ReadableStream | [ProtocolResponse](structures/protocol-response.md))
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully intercepted
|
||||||
|
|
||||||
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
|
Same as `protocol.registerStreamProtocol`, except that it replaces an existing
|
||||||
protocol handler.
|
protocol handler.
|
||||||
|
|
||||||
### `protocol.uninterceptProtocol(scheme[, completion])`
|
### `protocol.uninterceptProtocol(scheme)`
|
||||||
|
|
||||||
* `scheme` String
|
* `scheme` String
|
||||||
* `completion` Function (optional)
|
|
||||||
* `error` Error
|
Returns `Boolean` - Whether the protocol was successfully unintercepted
|
||||||
|
|
||||||
Remove the interceptor installed for `scheme` and restore its original handler.
|
Remove the interceptor installed for `scheme` and restore its original handler.
|
||||||
|
|
||||||
[net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
|
### `protocol.isProtocolIntercepted(scheme)`
|
||||||
|
|
||||||
|
* `scheme` String
|
||||||
|
|
||||||
|
Returns `Boolean` - Whether `scheme` is already intercepted.
|
||||||
|
|
||||||
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
|
[file-system-api]: https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem
|
||||||
|
|
|
@ -4,3 +4,4 @@
|
||||||
* `referrer` String
|
* `referrer` String
|
||||||
* `method` String
|
* `method` String
|
||||||
* `uploadData` [UploadData[]](upload-data.md) (optional)
|
* `uploadData` [UploadData[]](upload-data.md) (optional)
|
||||||
|
* `headers` Record<String, String>
|
||||||
|
|
|
@ -43,7 +43,6 @@ auto_filenames = {
|
||||||
"docs/api/power-monitor.md",
|
"docs/api/power-monitor.md",
|
||||||
"docs/api/power-save-blocker.md",
|
"docs/api/power-save-blocker.md",
|
||||||
"docs/api/process.md",
|
"docs/api/process.md",
|
||||||
"docs/api/protocol-ns.md",
|
|
||||||
"docs/api/protocol.md",
|
"docs/api/protocol.md",
|
||||||
"docs/api/remote.md",
|
"docs/api/remote.md",
|
||||||
"docs/api/sandbox-option.md",
|
"docs/api/sandbox-option.md",
|
||||||
|
|
|
@ -176,11 +176,12 @@ ProtocolError Protocol::RegisterProtocol(ProtocolType type,
|
||||||
return added ? ProtocolError::OK : ProtocolError::REGISTERED;
|
return added ? ProtocolError::OK : ProtocolError::REGISTERED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Protocol::UnregisterProtocol(const std::string& scheme,
|
bool Protocol::UnregisterProtocol(const std::string& scheme,
|
||||||
gin::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
bool removed = protocol_registry_->UnregisterProtocol(scheme);
|
bool removed = protocol_registry_->UnregisterProtocol(scheme);
|
||||||
HandleOptionalCallback(
|
HandleOptionalCallback(
|
||||||
args, removed ? ProtocolError::OK : ProtocolError::NOT_REGISTERED);
|
args, removed ? ProtocolError::OK : ProtocolError::NOT_REGISTERED);
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Protocol::IsProtocolRegistered(const std::string& scheme) {
|
bool Protocol::IsProtocolRegistered(const std::string& scheme) {
|
||||||
|
@ -194,11 +195,12 @@ ProtocolError Protocol::InterceptProtocol(ProtocolType type,
|
||||||
return added ? ProtocolError::OK : ProtocolError::INTERCEPTED;
|
return added ? ProtocolError::OK : ProtocolError::INTERCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Protocol::UninterceptProtocol(const std::string& scheme,
|
bool Protocol::UninterceptProtocol(const std::string& scheme,
|
||||||
gin::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
bool removed = protocol_registry_->UninterceptProtocol(scheme);
|
bool removed = protocol_registry_->UninterceptProtocol(scheme);
|
||||||
HandleOptionalCallback(
|
HandleOptionalCallback(
|
||||||
args, removed ? ProtocolError::OK : ProtocolError::NOT_INTERCEPTED);
|
args, removed ? ProtocolError::OK : ProtocolError::NOT_INTERCEPTED);
|
||||||
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Protocol::IsProtocolIntercepted(const std::string& scheme) {
|
bool Protocol::IsProtocolIntercepted(const std::string& scheme) {
|
||||||
|
|
|
@ -58,13 +58,13 @@ class Protocol : public gin::Wrappable<Protocol> {
|
||||||
ProtocolError RegisterProtocol(ProtocolType type,
|
ProtocolError RegisterProtocol(ProtocolType type,
|
||||||
const std::string& scheme,
|
const std::string& scheme,
|
||||||
const ProtocolHandler& handler);
|
const ProtocolHandler& handler);
|
||||||
void UnregisterProtocol(const std::string& scheme, gin::Arguments* args);
|
bool UnregisterProtocol(const std::string& scheme, gin::Arguments* args);
|
||||||
bool IsProtocolRegistered(const std::string& scheme);
|
bool IsProtocolRegistered(const std::string& scheme);
|
||||||
|
|
||||||
ProtocolError InterceptProtocol(ProtocolType type,
|
ProtocolError InterceptProtocol(ProtocolType type,
|
||||||
const std::string& scheme,
|
const std::string& scheme,
|
||||||
const ProtocolHandler& handler);
|
const ProtocolHandler& handler);
|
||||||
void UninterceptProtocol(const std::string& scheme, gin::Arguments* args);
|
bool UninterceptProtocol(const std::string& scheme, gin::Arguments* args);
|
||||||
bool IsProtocolIntercepted(const std::string& scheme);
|
bool IsProtocolIntercepted(const std::string& scheme);
|
||||||
|
|
||||||
// Old async version of IsProtocolRegistered.
|
// Old async version of IsProtocolRegistered.
|
||||||
|
@ -73,16 +73,20 @@ class Protocol : public gin::Wrappable<Protocol> {
|
||||||
|
|
||||||
// Helper for converting old registration APIs to new RegisterProtocol API.
|
// Helper for converting old registration APIs to new RegisterProtocol API.
|
||||||
template <ProtocolType type>
|
template <ProtocolType type>
|
||||||
void RegisterProtocolFor(const std::string& scheme,
|
bool RegisterProtocolFor(const std::string& scheme,
|
||||||
const ProtocolHandler& handler,
|
const ProtocolHandler& handler,
|
||||||
gin::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
HandleOptionalCallback(args, RegisterProtocol(type, scheme, handler));
|
auto result = RegisterProtocol(type, scheme, handler);
|
||||||
|
HandleOptionalCallback(args, result);
|
||||||
|
return result == ProtocolError::OK;
|
||||||
}
|
}
|
||||||
template <ProtocolType type>
|
template <ProtocolType type>
|
||||||
void InterceptProtocolFor(const std::string& scheme,
|
bool InterceptProtocolFor(const std::string& scheme,
|
||||||
const ProtocolHandler& handler,
|
const ProtocolHandler& handler,
|
||||||
gin::Arguments* args) {
|
gin::Arguments* args) {
|
||||||
HandleOptionalCallback(args, InterceptProtocol(type, scheme, handler));
|
auto result = InterceptProtocol(type, scheme, handler);
|
||||||
|
HandleOptionalCallback(args, result);
|
||||||
|
return result == ProtocolError::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Be compatible with old interface, which accepts optional callback.
|
// Be compatible with old interface, which accepts optional callback.
|
||||||
|
|
|
@ -241,10 +241,10 @@ describe('BrowserWindow module', () => {
|
||||||
let w = null as unknown as BrowserWindow;
|
let w = null as unknown as BrowserWindow;
|
||||||
const scheme = 'other';
|
const scheme = 'other';
|
||||||
const srcPath = path.join(fixtures, 'api', 'loaded-from-dataurl.js');
|
const srcPath = path.join(fixtures, 'api', 'loaded-from-dataurl.js');
|
||||||
before((done) => {
|
before(() => {
|
||||||
protocol.registerFileProtocol(scheme, (request, callback) => {
|
protocol.registerFileProtocol(scheme, (request, callback) => {
|
||||||
callback(srcPath);
|
callback(srcPath);
|
||||||
}, (error) => done(error));
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after(() => {
|
after(() => {
|
||||||
|
@ -2532,26 +2532,20 @@ describe('BrowserWindow module', () => {
|
||||||
['foo', path.join(fixtures, 'api', 'window-open-location-change.html')],
|
['foo', path.join(fixtures, 'api', 'window-open-location-change.html')],
|
||||||
['bar', path.join(fixtures, 'api', 'window-open-location-final.html')]
|
['bar', path.join(fixtures, 'api', 'window-open-location-final.html')]
|
||||||
];
|
];
|
||||||
beforeEach(async () => {
|
beforeEach(() => {
|
||||||
await Promise.all(protocols.map(([scheme, path]) => new Promise((resolve, reject) => {
|
for (const [scheme, path] of protocols) {
|
||||||
protocol.registerBufferProtocol(scheme, (request, callback) => {
|
protocol.registerBufferProtocol(scheme, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
mimeType: 'text/html',
|
mimeType: 'text/html',
|
||||||
data: fs.readFileSync(path)
|
data: fs.readFileSync(path)
|
||||||
});
|
});
|
||||||
}, (error) => {
|
});
|
||||||
if (error != null) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})));
|
afterEach(() => {
|
||||||
});
|
for (const [scheme] of protocols) {
|
||||||
afterEach(async () => {
|
protocol.unregisterProtocol(scheme);
|
||||||
await Promise.all(protocols.map(([scheme]) => {
|
}
|
||||||
return new Promise(resolve => protocol.unregisterProtocol(scheme, () => resolve()));
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
it('retains the original web preferences when window.location is changed to a new origin', async () => {
|
it('retains the original web preferences when window.location is changed to a new origin', async () => {
|
||||||
const w = new BrowserWindow({
|
const w = new BrowserWindow({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron/main';
|
import { protocol, webContents, WebContents, session, BrowserWindow, ipcMain } from 'electron/main';
|
||||||
import { promisify } from 'util';
|
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
import * as ChildProcess from 'child_process';
|
import * as ChildProcess from 'child_process';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
@ -13,17 +12,17 @@ import { emittedOnce } from './events-helpers';
|
||||||
|
|
||||||
const fixturesPath = path.resolve(__dirname, '..', 'spec', 'fixtures');
|
const fixturesPath = path.resolve(__dirname, '..', 'spec', 'fixtures');
|
||||||
|
|
||||||
const registerStringProtocol = promisify(protocol.registerStringProtocol);
|
const registerStringProtocol = protocol.registerStringProtocol;
|
||||||
const registerBufferProtocol = promisify(protocol.registerBufferProtocol);
|
const registerBufferProtocol = protocol.registerBufferProtocol;
|
||||||
const registerFileProtocol = promisify(protocol.registerFileProtocol);
|
const registerFileProtocol = protocol.registerFileProtocol;
|
||||||
const registerHttpProtocol = promisify(protocol.registerHttpProtocol);
|
const registerHttpProtocol = protocol.registerHttpProtocol;
|
||||||
const registerStreamProtocol = promisify(protocol.registerStreamProtocol);
|
const registerStreamProtocol = protocol.registerStreamProtocol;
|
||||||
const interceptStringProtocol = promisify(protocol.interceptStringProtocol);
|
const interceptStringProtocol = protocol.interceptStringProtocol;
|
||||||
const interceptBufferProtocol = promisify(protocol.interceptBufferProtocol);
|
const interceptBufferProtocol = protocol.interceptBufferProtocol;
|
||||||
const interceptHttpProtocol = promisify(protocol.interceptHttpProtocol);
|
const interceptHttpProtocol = protocol.interceptHttpProtocol;
|
||||||
const interceptStreamProtocol = promisify(protocol.interceptStreamProtocol);
|
const interceptStreamProtocol = protocol.interceptStreamProtocol;
|
||||||
const unregisterProtocol = promisify(protocol.unregisterProtocol);
|
const unregisterProtocol = protocol.unregisterProtocol;
|
||||||
const uninterceptProtocol = promisify(protocol.uninterceptProtocol);
|
const uninterceptProtocol = protocol.uninterceptProtocol;
|
||||||
|
|
||||||
const text = 'valar morghulis';
|
const text = 'valar morghulis';
|
||||||
const protocolName = 'sp';
|
const protocolName = 'sp';
|
||||||
|
@ -87,22 +86,22 @@ describe('protocol module', () => {
|
||||||
return contents.executeJavaScript(`ajax("${url}", ${JSON.stringify(options)})`);
|
return contents.executeJavaScript(`ajax("${url}", ${JSON.stringify(options)})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(() => {
|
||||||
await new Promise(resolve => protocol.unregisterProtocol(protocolName, (/* ignore error */) => resolve()));
|
protocol.unregisterProtocol(protocolName);
|
||||||
await new Promise(resolve => protocol.uninterceptProtocol('http', () => resolve()));
|
protocol.uninterceptProtocol('http');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.register(Any)Protocol', () => {
|
describe('protocol.register(Any)Protocol', () => {
|
||||||
it('throws error when scheme is already registered', async () => {
|
it('fails when scheme is already registered', () => {
|
||||||
await registerStringProtocol(protocolName, (req, cb) => cb());
|
expect(registerStringProtocol(protocolName, (req, cb) => cb(''))).to.equal(true);
|
||||||
await expect(registerBufferProtocol(protocolName, (req, cb) => cb())).to.be.eventually.rejectedWith(Error);
|
expect(registerBufferProtocol(protocolName, (req, cb) => cb(Buffer.from('')))).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not crash when handler is called twice', async () => {
|
it('does not crash when handler is called twice', async () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => {
|
registerStringProtocol(protocolName, (request, callback) => {
|
||||||
try {
|
try {
|
||||||
callback(text);
|
callback(text);
|
||||||
callback();
|
callback('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Ignore error
|
// Ignore error
|
||||||
}
|
}
|
||||||
|
@ -112,12 +111,12 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends error when callback is called with nothing', async () => {
|
it('sends error when callback is called with nothing', async () => {
|
||||||
await registerBufferProtocol(protocolName, (req, cb) => cb());
|
registerBufferProtocol(protocolName, (req, cb: any) => cb());
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.eventually.be.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not crash when callback is called in next tick', async () => {
|
it('does not crash when callback is called in next tick', async () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => {
|
registerStringProtocol(protocolName, (request, callback) => {
|
||||||
setImmediate(() => callback(text));
|
setImmediate(() => callback(text));
|
||||||
});
|
});
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
|
@ -126,27 +125,27 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.unregisterProtocol', () => {
|
describe('protocol.unregisterProtocol', () => {
|
||||||
it('returns error when scheme does not exist', async () => {
|
it('returns false when scheme does not exist', () => {
|
||||||
await expect(unregisterProtocol('not-exist')).to.be.eventually.rejectedWith(Error);
|
expect(unregisterProtocol('not-exist')).to.equal(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.registerStringProtocol', () => {
|
describe('protocol.registerStringProtocol', () => {
|
||||||
it('sends string as response', async () => {
|
it('sends string as response', async () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => callback(text));
|
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets Access-Control-Allow-Origin', async () => {
|
it('sets Access-Control-Allow-Origin', async () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => callback(text));
|
registerStringProtocol(protocolName, (request, callback) => callback(text));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
expect(r.headers).to.include('access-control-allow-origin: *');
|
expect(r.headers).to.include('access-control-allow-origin: *');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends object as response', async () => {
|
it('sends object as response', async () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => {
|
registerStringProtocol(protocolName, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
data: text,
|
data: text,
|
||||||
mimeType: 'text/html'
|
mimeType: 'text/html'
|
||||||
|
@ -158,7 +157,7 @@ describe('protocol module', () => {
|
||||||
|
|
||||||
it('fails when sending object other than string', async () => {
|
it('fails when sending object other than string', async () => {
|
||||||
const notAString = () => {};
|
const notAString = () => {};
|
||||||
await registerStringProtocol(protocolName, (request, callback) => callback(notAString as any));
|
registerStringProtocol(protocolName, (request, callback) => callback(notAString as any));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -166,20 +165,20 @@ describe('protocol module', () => {
|
||||||
describe('protocol.registerBufferProtocol', () => {
|
describe('protocol.registerBufferProtocol', () => {
|
||||||
const buffer = Buffer.from(text);
|
const buffer = Buffer.from(text);
|
||||||
it('sends Buffer as response', async () => {
|
it('sends Buffer as response', async () => {
|
||||||
await registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets Access-Control-Allow-Origin', async () => {
|
it('sets Access-Control-Allow-Origin', async () => {
|
||||||
await registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
registerBufferProtocol(protocolName, (request, callback) => callback(buffer));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
expect(r.headers).to.include('access-control-allow-origin: *');
|
expect(r.headers).to.include('access-control-allow-origin: *');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends object as response', async () => {
|
it('sends object as response', async () => {
|
||||||
await registerBufferProtocol(protocolName, (request, callback) => {
|
registerBufferProtocol(protocolName, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
data: buffer,
|
data: buffer,
|
||||||
mimeType: 'text/html'
|
mimeType: 'text/html'
|
||||||
|
@ -190,7 +189,7 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when sending string', async () => {
|
it('fails when sending string', async () => {
|
||||||
await registerBufferProtocol(protocolName, (request, callback) => callback(text as any));
|
registerBufferProtocol(protocolName, (request, callback) => callback(text as any));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -202,20 +201,20 @@ describe('protocol module', () => {
|
||||||
const normalContent = fs.readFileSync(normalPath);
|
const normalContent = fs.readFileSync(normalPath);
|
||||||
|
|
||||||
it('sends file path as response', async () => {
|
it('sends file path as response', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(String(fileContent));
|
expect(r.data).to.equal(String(fileContent));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets Access-Control-Allow-Origin', async () => {
|
it('sets Access-Control-Allow-Origin', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
registerFileProtocol(protocolName, (request, callback) => callback(filePath));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(String(fileContent));
|
expect(r.data).to.equal(String(fileContent));
|
||||||
expect(r.headers).to.include('access-control-allow-origin: *');
|
expect(r.headers).to.include('access-control-allow-origin: *');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets custom headers', async () => {
|
it('sets custom headers', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback({
|
registerFileProtocol(protocolName, (request, callback) => callback({
|
||||||
path: filePath,
|
path: filePath,
|
||||||
headers: { 'X-Great-Header': 'sogreat' }
|
headers: { 'X-Great-Header': 'sogreat' }
|
||||||
}));
|
}));
|
||||||
|
@ -231,31 +230,30 @@ describe('protocol module', () => {
|
||||||
headers: { 'X-Great-Header': (42 as any) }
|
headers: { 'X-Great-Header': (42 as any) }
|
||||||
})).to.throw(Error, 'Value of \'X-Great-Header\' header has to be a string');
|
})).to.throw(Error, 'Value of \'X-Great-Header\' header has to be a string');
|
||||||
done();
|
done();
|
||||||
}).then(() => {
|
|
||||||
ajax(protocolName + '://fake-host');
|
|
||||||
});
|
});
|
||||||
|
ajax(protocolName + '://fake-host');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends object as response', async () => {
|
it('sends object as response', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback({ path: filePath }));
|
registerFileProtocol(protocolName, (request, callback) => callback({ path: filePath }));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(String(fileContent));
|
expect(r.data).to.equal(String(fileContent));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can send normal file', async () => {
|
it('can send normal file', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback(normalPath));
|
registerFileProtocol(protocolName, (request, callback) => callback(normalPath));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(String(normalContent));
|
expect(r.data).to.equal(String(normalContent));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when sending unexist-file', async () => {
|
it('fails when sending unexist-file', async () => {
|
||||||
const fakeFilePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'not-exist');
|
const fakeFilePath = path.join(fixturesPath, 'test.asar', 'a.asar', 'not-exist');
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback(fakeFilePath));
|
registerFileProtocol(protocolName, (request, callback) => callback(fakeFilePath));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when sending unsupported content', async () => {
|
it('fails when sending unsupported content', async () => {
|
||||||
await registerFileProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
registerFileProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -267,22 +265,22 @@ describe('protocol module', () => {
|
||||||
res.end(text);
|
res.end(text);
|
||||||
server.close();
|
server.close();
|
||||||
});
|
});
|
||||||
await server.listen(0, '127.0.0.1');
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||||
|
|
||||||
const port = (server.address() as AddressInfo).port;
|
const port = (server.address() as AddressInfo).port;
|
||||||
const url = 'http://127.0.0.1:' + port;
|
const url = 'http://127.0.0.1:' + port;
|
||||||
await registerHttpProtocol(protocolName, (request, callback) => callback({ url }));
|
registerHttpProtocol(protocolName, (request, callback) => callback({ url }));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when sending invalid url', async () => {
|
it('fails when sending invalid url', async () => {
|
||||||
await registerHttpProtocol(protocolName, (request, callback) => callback({ url: 'url' }));
|
registerHttpProtocol(protocolName, (request, callback) => callback({ url: 'url' }));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails when sending unsupported content', async () => {
|
it('fails when sending unsupported content', async () => {
|
||||||
await registerHttpProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
registerHttpProtocol(protocolName, (request, callback) => callback(new Date() as any));
|
||||||
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax(protocolName + '://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -297,12 +295,12 @@ describe('protocol module', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
after(() => server.close());
|
after(() => server.close());
|
||||||
await server.listen(0, '127.0.0.1');
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||||
|
|
||||||
const port = (server.address() as AddressInfo).port;
|
const port = (server.address() as AddressInfo).port;
|
||||||
const url = `${protocolName}://fake-host`;
|
const url = `${protocolName}://fake-host`;
|
||||||
const redirectURL = `http://127.0.0.1:${port}/serverRedirect`;
|
const redirectURL = `http://127.0.0.1:${port}/serverRedirect`;
|
||||||
await registerHttpProtocol(protocolName, (request, callback) => callback({ url: redirectURL }));
|
registerHttpProtocol(protocolName, (request, callback) => callback({ url: redirectURL }));
|
||||||
|
|
||||||
const r = await ajax(url);
|
const r = await ajax(url);
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
|
@ -312,28 +310,27 @@ describe('protocol module', () => {
|
||||||
protocol.registerHttpProtocol(protocolName, (request) => {
|
protocol.registerHttpProtocol(protocolName, (request) => {
|
||||||
expect(request).to.have.property('headers');
|
expect(request).to.have.property('headers');
|
||||||
done();
|
done();
|
||||||
}, () => {
|
|
||||||
ajax(protocolName + '://fake-host');
|
|
||||||
});
|
});
|
||||||
|
ajax(protocolName + '://fake-host');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.registerStreamProtocol', () => {
|
describe('protocol.registerStreamProtocol', () => {
|
||||||
it('sends Stream as response', async () => {
|
it('sends Stream as response', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => callback(getStream()));
|
registerStreamProtocol(protocolName, (request, callback) => callback(getStream()));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends object as response', async () => {
|
it('sends object as response', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => callback({ data: getStream() }));
|
registerStreamProtocol(protocolName, (request, callback) => callback({ data: getStream() }));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
expect(r.status).to.equal(200);
|
expect(r.status).to.equal(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends custom response headers', async () => {
|
it('sends custom response headers', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => callback({
|
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||||
data: getStream(3),
|
data: getStream(3),
|
||||||
headers: {
|
headers: {
|
||||||
'x-electron': ['a', 'b']
|
'x-electron': ['a', 'b']
|
||||||
|
@ -346,9 +343,9 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends custom status code', async () => {
|
it('sends custom status code', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => callback({
|
registerStreamProtocol(protocolName, (request, callback) => callback({
|
||||||
statusCode: 204,
|
statusCode: 204,
|
||||||
data: null
|
data: null as any
|
||||||
}));
|
}));
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
expect(r.data).to.be.undefined('data');
|
expect(r.data).to.be.undefined('data');
|
||||||
|
@ -356,7 +353,7 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('receives request headers', async () => {
|
it('receives request headers', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => {
|
registerStreamProtocol(protocolName, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
headers: {
|
headers: {
|
||||||
'content-type': 'application/json'
|
'content-type': 'application/json'
|
||||||
|
@ -369,7 +366,7 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns response multiple response headers with the same name', async () => {
|
it('returns response multiple response headers with the same name', async () => {
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => {
|
registerStreamProtocol(protocolName, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
headers: {
|
headers: {
|
||||||
header1: ['value1', 'value2'],
|
header1: ['value1', 'value2'],
|
||||||
|
@ -387,7 +384,7 @@ describe('protocol module', () => {
|
||||||
|
|
||||||
it('can handle large responses', async () => {
|
it('can handle large responses', async () => {
|
||||||
const data = Buffer.alloc(128 * 1024);
|
const data = Buffer.alloc(128 * 1024);
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => {
|
registerStreamProtocol(protocolName, (request, callback) => {
|
||||||
callback(getStream(data.length, data));
|
callback(getStream(data.length, data));
|
||||||
});
|
});
|
||||||
const r = await ajax(protocolName + '://fake-host');
|
const r = await ajax(protocolName + '://fake-host');
|
||||||
|
@ -402,7 +399,7 @@ describe('protocol module', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await registerStreamProtocol(protocolName, (request, callback) => {
|
registerStreamProtocol(protocolName, (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
headers: { 'Content-Type': 'text/plain' },
|
headers: { 'Content-Type': 'text/plain' },
|
||||||
|
@ -414,48 +411,38 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.isProtocolHandled', () => {
|
describe('protocol.isProtocolRegistered', () => {
|
||||||
it('returns true for built-in protocols', async () => {
|
it('returns false when scheme is not registered', () => {
|
||||||
for (const p of ['about', 'file', 'http', 'https']) {
|
const result = protocol.isProtocolRegistered('no-exist');
|
||||||
const handled = await protocol.isProtocolHandled(p);
|
|
||||||
expect(handled).to.be.true(`${p}: is handled`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns false when scheme is not registered', async () => {
|
|
||||||
const result = await protocol.isProtocolHandled('no-exist');
|
|
||||||
expect(result).to.be.false('no-exist: is handled');
|
expect(result).to.be.false('no-exist: is handled');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns true for custom protocol', async () => {
|
it('returns true for custom protocol', () => {
|
||||||
await registerStringProtocol(protocolName, (request, callback) => callback());
|
registerStringProtocol(protocolName, (request, callback) => callback(''));
|
||||||
const result = await protocol.isProtocolHandled(protocolName);
|
const result = protocol.isProtocolRegistered(protocolName);
|
||||||
expect(result).to.be.true('custom protocol is handled');
|
expect(result).to.be.true('custom protocol is handled');
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('returns true for intercepted protocol', async () => {
|
describe('protocol.isProtocolIntercepted', () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => callback());
|
it('returns true for intercepted protocol', () => {
|
||||||
const result = await protocol.isProtocolHandled('http');
|
interceptStringProtocol('http', (request, callback) => callback(''));
|
||||||
|
const result = protocol.isProtocolIntercepted('http');
|
||||||
expect(result).to.be.true('intercepted protocol is handled');
|
expect(result).to.be.true('intercepted protocol is handled');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.intercept(Any)Protocol', () => {
|
describe('protocol.intercept(Any)Protocol', () => {
|
||||||
it('throws error when scheme is already intercepted', (done) => {
|
it('returns false when scheme is already intercepted', () => {
|
||||||
protocol.interceptStringProtocol('http', (request, callback) => callback(), (error) => {
|
expect(protocol.interceptStringProtocol('http', (request, callback) => callback(''))).to.equal(true);
|
||||||
expect(error).to.be.null('error');
|
expect(protocol.interceptBufferProtocol('http', (request, callback) => callback(Buffer.from('')))).to.equal(false);
|
||||||
protocol.interceptBufferProtocol('http', (request, callback) => callback(), (error) => {
|
|
||||||
expect(error).to.not.be.null('error');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not crash when handler is called twice', async () => {
|
it('does not crash when handler is called twice', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => {
|
interceptStringProtocol('http', (request, callback) => {
|
||||||
try {
|
try {
|
||||||
callback(text);
|
callback(text);
|
||||||
callback();
|
callback('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Ignore error
|
// Ignore error
|
||||||
}
|
}
|
||||||
|
@ -465,20 +452,20 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sends error when callback is called with nothing', async () => {
|
it('sends error when callback is called with nothing', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => callback());
|
interceptStringProtocol('http', (request, callback: any) => callback());
|
||||||
await expect(ajax('http://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
await expect(ajax('http://fake-host')).to.be.eventually.rejectedWith(Error, '404');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.interceptStringProtocol', () => {
|
describe('protocol.interceptStringProtocol', () => {
|
||||||
it('can intercept http protocol', async () => {
|
it('can intercept http protocol', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => callback(text));
|
interceptStringProtocol('http', (request, callback) => callback(text));
|
||||||
const r = await ajax('http://fake-host');
|
const r = await ajax('http://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can set content-type', async () => {
|
it('can set content-type', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => {
|
interceptStringProtocol('http', (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
mimeType: 'application/json',
|
mimeType: 'application/json',
|
||||||
data: '{"value": 1}'
|
data: '{"value": 1}'
|
||||||
|
@ -490,7 +477,7 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can set content-type with charset', async () => {
|
it('can set content-type with charset', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => {
|
interceptStringProtocol('http', (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
mimeType: 'application/json; charset=UTF-8',
|
mimeType: 'application/json; charset=UTF-8',
|
||||||
data: '{"value": 1}'
|
data: '{"value": 1}'
|
||||||
|
@ -502,8 +489,8 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can receive post data', async () => {
|
it('can receive post data', async () => {
|
||||||
await interceptStringProtocol('http', (request, callback) => {
|
interceptStringProtocol('http', (request, callback) => {
|
||||||
const uploadData = request.uploadData[0].bytes.toString();
|
const uploadData = request.uploadData![0].bytes.toString();
|
||||||
callback({ data: uploadData });
|
callback({ data: uploadData });
|
||||||
});
|
});
|
||||||
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
||||||
|
@ -513,14 +500,14 @@ describe('protocol module', () => {
|
||||||
|
|
||||||
describe('protocol.interceptBufferProtocol', () => {
|
describe('protocol.interceptBufferProtocol', () => {
|
||||||
it('can intercept http protocol', async () => {
|
it('can intercept http protocol', async () => {
|
||||||
await interceptBufferProtocol('http', (request, callback) => callback(Buffer.from(text)));
|
interceptBufferProtocol('http', (request, callback) => callback(Buffer.from(text)));
|
||||||
const r = await ajax('http://fake-host');
|
const r = await ajax('http://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can receive post data', async () => {
|
it('can receive post data', async () => {
|
||||||
await interceptBufferProtocol('http', (request, callback) => {
|
interceptBufferProtocol('http', (request, callback) => {
|
||||||
const uploadData = request.uploadData[0].bytes;
|
const uploadData = request.uploadData![0].bytes;
|
||||||
callback(uploadData);
|
callback(uploadData);
|
||||||
});
|
});
|
||||||
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
||||||
|
@ -544,19 +531,19 @@ describe('protocol module', () => {
|
||||||
server.close();
|
server.close();
|
||||||
});
|
});
|
||||||
after(() => server.close());
|
after(() => server.close());
|
||||||
await server.listen(0, '127.0.0.1');
|
server.listen(0, '127.0.0.1');
|
||||||
|
|
||||||
const port = (server.address() as AddressInfo).port;
|
const port = (server.address() as AddressInfo).port;
|
||||||
const url = `http://127.0.0.1:${port}`;
|
const url = `http://127.0.0.1:${port}`;
|
||||||
await interceptHttpProtocol('http', (request, callback) => {
|
interceptHttpProtocol('http', (request, callback) => {
|
||||||
const data: Electron.RedirectRequest = {
|
const data: Electron.ProtocolResponse = {
|
||||||
url: url,
|
url: url,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
uploadData: {
|
uploadData: {
|
||||||
contentType: 'application/x-www-form-urlencoded',
|
contentType: 'application/x-www-form-urlencoded',
|
||||||
data: request.uploadData[0].bytes
|
data: request.uploadData![0].bytes
|
||||||
},
|
},
|
||||||
session: null
|
session: undefined
|
||||||
};
|
};
|
||||||
callback(data);
|
callback(data);
|
||||||
});
|
});
|
||||||
|
@ -572,7 +559,7 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
after(() => customSession.webRequest.onBeforeRequest(null));
|
after(() => customSession.webRequest.onBeforeRequest(null));
|
||||||
|
|
||||||
await interceptHttpProtocol('http', (request, callback) => {
|
interceptHttpProtocol('http', (request, callback) => {
|
||||||
callback({
|
callback({
|
||||||
url: request.url,
|
url: request.url,
|
||||||
session: customSession
|
session: customSession
|
||||||
|
@ -585,33 +572,32 @@ describe('protocol module', () => {
|
||||||
protocol.interceptHttpProtocol('http', (request) => {
|
protocol.interceptHttpProtocol('http', (request) => {
|
||||||
expect(request).to.have.property('headers');
|
expect(request).to.have.property('headers');
|
||||||
done();
|
done();
|
||||||
}, () => {
|
|
||||||
ajax('http://fake-host');
|
|
||||||
});
|
});
|
||||||
|
ajax('http://fake-host');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.interceptStreamProtocol', () => {
|
describe('protocol.interceptStreamProtocol', () => {
|
||||||
it('can intercept http protocol', async () => {
|
it('can intercept http protocol', async () => {
|
||||||
await interceptStreamProtocol('http', (request, callback) => callback(getStream()));
|
interceptStreamProtocol('http', (request, callback) => callback(getStream()));
|
||||||
const r = await ajax('http://fake-host');
|
const r = await ajax('http://fake-host');
|
||||||
expect(r.data).to.equal(text);
|
expect(r.data).to.equal(text);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can receive post data', async () => {
|
it('can receive post data', async () => {
|
||||||
await interceptStreamProtocol('http', (request, callback) => {
|
interceptStreamProtocol('http', (request, callback) => {
|
||||||
callback(getStream(3, request.uploadData[0].bytes.toString()));
|
callback(getStream(3, request.uploadData![0].bytes.toString()));
|
||||||
});
|
});
|
||||||
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
const r = await ajax('http://fake-host', { type: 'POST', data: postData });
|
||||||
expect({ ...qs.parse(r.data) }).to.deep.equal(postData);
|
expect({ ...qs.parse(r.data) }).to.deep.equal(postData);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can execute redirects', async () => {
|
it('can execute redirects', async () => {
|
||||||
await interceptStreamProtocol('http', (request, callback) => {
|
interceptStreamProtocol('http', (request, callback) => {
|
||||||
if (request.url.indexOf('http://fake-host') === 0) {
|
if (request.url.indexOf('http://fake-host') === 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
callback({
|
callback({
|
||||||
data: null,
|
data: '',
|
||||||
statusCode: 302,
|
statusCode: 302,
|
||||||
headers: {
|
headers: {
|
||||||
Location: 'http://fake-redirect'
|
Location: 'http://fake-redirect'
|
||||||
|
@ -629,12 +615,12 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('protocol.uninterceptProtocol', () => {
|
describe('protocol.uninterceptProtocol', () => {
|
||||||
it('returns error when scheme does not exist', async () => {
|
it('returns false when scheme does not exist', () => {
|
||||||
await expect(uninterceptProtocol('not-exist')).to.be.eventually.rejectedWith(Error);
|
expect(uninterceptProtocol('not-exist')).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns error when scheme is not intercepted', async () => {
|
it('returns false when scheme is not intercepted', () => {
|
||||||
await expect(uninterceptProtocol('http')).to.be.eventually.rejectedWith(Error);
|
expect(uninterceptProtocol('http')).to.equal(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -677,14 +663,14 @@ describe('protocol module', () => {
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await closeWindow(w);
|
await closeWindow(w);
|
||||||
await unregisterProtocol(standardScheme);
|
unregisterProtocol(standardScheme);
|
||||||
w = null as unknown as BrowserWindow;
|
w = null as unknown as BrowserWindow;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves relative resources', async () => {
|
it('resolves relative resources', async () => {
|
||||||
await registerFileProtocol(standardScheme, (request, callback) => {
|
registerFileProtocol(standardScheme, (request, callback) => {
|
||||||
if (request.url === imageURL) {
|
if (request.url === imageURL) {
|
||||||
callback();
|
callback('');
|
||||||
} else {
|
} else {
|
||||||
callback(filePath);
|
callback(filePath);
|
||||||
}
|
}
|
||||||
|
@ -693,9 +679,9 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves absolute resources', async () => {
|
it('resolves absolute resources', async () => {
|
||||||
await registerStringProtocol(standardScheme, (request, callback) => {
|
registerStringProtocol(standardScheme, (request, callback) => {
|
||||||
if (request.url === imageURL) {
|
if (request.url === imageURL) {
|
||||||
callback();
|
callback('');
|
||||||
} else {
|
} else {
|
||||||
callback({
|
callback({
|
||||||
data: fileContent,
|
data: fileContent,
|
||||||
|
@ -716,17 +702,15 @@ describe('protocol module', () => {
|
||||||
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||||
const port = (server.address() as AddressInfo).port;
|
const port = (server.address() as AddressInfo).port;
|
||||||
const content = `<script>fetch("http://127.0.0.1:${port}")</script>`;
|
const content = `<script>fetch("http://127.0.0.1:${port}")</script>`;
|
||||||
await registerStringProtocol(standardScheme, (request, callback) => callback({ data: content, mimeType: 'text/html' }));
|
registerStringProtocol(standardScheme, (request, callback) => callback({ data: content, mimeType: 'text/html' }));
|
||||||
await w.loadURL(origin);
|
await w.loadURL(origin);
|
||||||
await requestReceived;
|
await requestReceived;
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('can access files through the FileSystem API', (done) => {
|
it.skip('can access files through the FileSystem API', (done) => {
|
||||||
const filePath = path.join(fixturesPath, 'pages', 'filesystem.html');
|
const filePath = path.join(fixturesPath, 'pages', 'filesystem.html');
|
||||||
protocol.registerFileProtocol(standardScheme, (request, callback) => callback({ path: filePath }), (error) => {
|
protocol.registerFileProtocol(standardScheme, (request, callback) => callback({ path: filePath }));
|
||||||
if (error) return done(error);
|
|
||||||
w.loadURL(origin);
|
w.loadURL(origin);
|
||||||
});
|
|
||||||
ipcMain.once('file-system-error', (event, err) => done(err));
|
ipcMain.once('file-system-error', (event, err) => done(err));
|
||||||
ipcMain.once('file-system-write-end', () => done());
|
ipcMain.once('file-system-write-end', () => done());
|
||||||
});
|
});
|
||||||
|
@ -735,12 +719,10 @@ describe('protocol module', () => {
|
||||||
const filePath = path.join(fixturesPath, 'pages', 'cache-storage.html');
|
const filePath = path.join(fixturesPath, 'pages', 'cache-storage.html');
|
||||||
ipcMain.once('success', () => done());
|
ipcMain.once('success', () => done());
|
||||||
ipcMain.once('failure', (event, err) => done(err));
|
ipcMain.once('failure', (event, err) => done(err));
|
||||||
protocol.registerFileProtocol(standardScheme, (request, callback) => callback({ path: filePath }), (error) => {
|
protocol.registerFileProtocol(standardScheme, (request, callback) => callback({ path: filePath }));
|
||||||
if (error) return done(error);
|
|
||||||
w.loadURL(origin);
|
w.loadURL(origin);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe.skip('protocol.registerSchemesAsPrivileged cors-fetch', function () {
|
describe.skip('protocol.registerSchemesAsPrivileged cors-fetch', function () {
|
||||||
const standardScheme = (global as any).standardScheme;
|
const standardScheme = (global as any).standardScheme;
|
||||||
|
@ -752,11 +734,9 @@ describe('protocol module', () => {
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await closeWindow(w);
|
await closeWindow(w);
|
||||||
w = null as unknown as BrowserWindow;
|
w = null as unknown as BrowserWindow;
|
||||||
await Promise.all(
|
for (const scheme of [standardScheme, 'cors', 'no-cors', 'no-fetch']) {
|
||||||
[standardScheme, 'cors', 'no-cors', 'no-fetch'].map(scheme =>
|
protocol.unregisterProtocol(scheme);
|
||||||
new Promise(resolve => protocol.unregisterProtocol(scheme, (/* ignore error */) => resolve()))
|
}
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports fetch api by default', async () => {
|
it('supports fetch api by default', async () => {
|
||||||
|
@ -818,10 +798,10 @@ describe('protocol module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function allowsCORSRequests (corsScheme: string, expected: any, expectedConsole: RegExp, content: Function) {
|
async function allowsCORSRequests (corsScheme: string, expected: any, expectedConsole: RegExp, content: Function) {
|
||||||
await registerStringProtocol(standardScheme, (request, callback) => {
|
registerStringProtocol(standardScheme, (request, callback) => {
|
||||||
callback({ data: `<script>(${content})()</script>`, mimeType: 'text/html' });
|
callback({ data: `<script>(${content})()</script>`, mimeType: 'text/html' });
|
||||||
});
|
});
|
||||||
await registerStringProtocol(corsScheme, (request, callback) => {
|
registerStringProtocol(corsScheme, (request, callback) => {
|
||||||
callback('');
|
callback('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -312,11 +312,11 @@ describe('session module', () => {
|
||||||
});
|
});
|
||||||
afterEach(closeAllWindows);
|
afterEach(closeAllWindows);
|
||||||
|
|
||||||
it('does not affect defaultSession', async () => {
|
it('does not affect defaultSession', () => {
|
||||||
const result1 = await protocol.isProtocolHandled(protocolName);
|
const result1 = protocol.isProtocolRegistered(protocolName);
|
||||||
expect(result1).to.equal(false);
|
expect(result1).to.equal(false);
|
||||||
|
|
||||||
const result2 = await customSession.protocol.isProtocolHandled(protocolName);
|
const result2 = customSession.protocol.isProtocolRegistered(protocolName);
|
||||||
expect(result2).to.equal(true);
|
expect(result2).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -424,20 +424,18 @@ describe('session module', () => {
|
||||||
if (request.method === 'GET') {
|
if (request.method === 'GET') {
|
||||||
callback({ data: content, mimeType: 'text/html' });
|
callback({ data: content, mimeType: 'text/html' });
|
||||||
} else if (request.method === 'POST') {
|
} else if (request.method === 'POST') {
|
||||||
const uuid = request.uploadData[1].blobUUID;
|
const uuid = request.uploadData![1].blobUUID;
|
||||||
expect(uuid).to.be.a('string');
|
expect(uuid).to.be.a('string');
|
||||||
session.defaultSession.getBlobData(uuid!).then(result => {
|
session.defaultSession.getBlobData(uuid!).then(result => {
|
||||||
expect(result.toString()).to.equal(postData);
|
expect(result.toString()).to.equal(postData);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, (error) => {
|
});
|
||||||
if (error) return done(error);
|
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.loadURL(url);
|
w.loadURL(url);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('ses.setCertificateVerifyProc(callback)', () => {
|
describe('ses.setCertificateVerifyProc(callback)', () => {
|
||||||
let server: http.Server;
|
let server: http.Server;
|
||||||
|
@ -644,8 +642,7 @@ describe('session module', () => {
|
||||||
const handler = (ignoredError: any, callback: Function) => {
|
const handler = (ignoredError: any, callback: Function) => {
|
||||||
callback({ url: `${url}:${port}` });
|
callback({ url: `${url}:${port}` });
|
||||||
};
|
};
|
||||||
protocol.registerHttpProtocol(protocolName, handler, (error) => {
|
protocol.registerHttpProtocol(protocolName, handler);
|
||||||
if (error) return done(error);
|
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.webContents.session.once('will-download', function (e, item) {
|
w.webContents.session.once('will-download', function (e, item) {
|
||||||
item.savePath = downloadFilePath;
|
item.savePath = downloadFilePath;
|
||||||
|
@ -656,7 +653,6 @@ describe('session module', () => {
|
||||||
});
|
});
|
||||||
w.webContents.downloadURL(`${protocolName}://item`);
|
w.webContents.downloadURL(`${protocolName}://item`);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('can download using WebView.downloadURL', async () => {
|
it('can download using WebView.downloadURL', async () => {
|
||||||
const port = address.port;
|
const port = address.port;
|
||||||
|
|
|
@ -830,7 +830,7 @@ describe('webContents module', () => {
|
||||||
host3: 0.2
|
host3: 0.2
|
||||||
};
|
};
|
||||||
|
|
||||||
before((done) => {
|
before(() => {
|
||||||
const protocol = session.defaultSession.protocol;
|
const protocol = session.defaultSession.protocol;
|
||||||
protocol.registerStringProtocol(scheme, (request, callback) => {
|
protocol.registerStringProtocol(scheme, (request, callback) => {
|
||||||
const response = `<script>
|
const response = `<script>
|
||||||
|
@ -841,12 +841,12 @@ describe('webContents module', () => {
|
||||||
})
|
})
|
||||||
</script>`;
|
</script>`;
|
||||||
callback({ data: response, mimeType: 'text/html' });
|
callback({ data: response, mimeType: 'text/html' });
|
||||||
}, (error) => done(error));
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after((done) => {
|
after(() => {
|
||||||
const protocol = session.defaultSession.protocol;
|
const protocol = session.defaultSession.protocol;
|
||||||
protocol.unregisterProtocol(scheme, (error) => done(error));
|
protocol.unregisterProtocol(scheme);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(closeAllWindows);
|
afterEach(closeAllWindows);
|
||||||
|
@ -981,8 +981,7 @@ describe('webContents module', () => {
|
||||||
const protocol = w2.webContents.session.protocol;
|
const protocol = w2.webContents.session.protocol;
|
||||||
protocol.registerStringProtocol(scheme, (request, callback) => {
|
protocol.registerStringProtocol(scheme, (request, callback) => {
|
||||||
callback('hello');
|
callback('hello');
|
||||||
}, (error) => {
|
});
|
||||||
if (error) return done(error);
|
|
||||||
w2.webContents.on('did-finish-load', () => {
|
w2.webContents.on('did-finish-load', () => {
|
||||||
const zoomLevel1 = w.webContents.zoomLevel;
|
const zoomLevel1 = w.webContents.zoomLevel;
|
||||||
expect(zoomLevel1).to.equal(hostZoomMap.host3);
|
expect(zoomLevel1).to.equal(hostZoomMap.host3);
|
||||||
|
@ -991,20 +990,17 @@ describe('webContents module', () => {
|
||||||
expect(zoomLevel2).to.equal(0);
|
expect(zoomLevel2).to.equal(0);
|
||||||
expect(zoomLevel1).to.not.equal(zoomLevel2);
|
expect(zoomLevel1).to.not.equal(zoomLevel2);
|
||||||
|
|
||||||
protocol.unregisterProtocol(scheme, (error) => {
|
protocol.unregisterProtocol(scheme);
|
||||||
if (error) return done(error);
|
|
||||||
w2.setClosable(true);
|
w2.setClosable(true);
|
||||||
w2.close();
|
w2.close();
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
|
||||||
w.webContents.on('did-finish-load', () => {
|
w.webContents.on('did-finish-load', () => {
|
||||||
w.webContents.zoomLevel = hostZoomMap.host3;
|
w.webContents.zoomLevel = hostZoomMap.host3;
|
||||||
w2.loadURL(`${scheme}://host3`);
|
w2.loadURL(`${scheme}://host3`);
|
||||||
});
|
});
|
||||||
w.loadURL(`${scheme}://host3`);
|
w.loadURL(`${scheme}://host3`);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it('can persist when it contains iframe', (done) => {
|
it('can persist when it contains iframe', (done) => {
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
|
|
|
@ -410,8 +410,6 @@ describe('chromium features', () => {
|
||||||
|
|
||||||
if (ext === '.js') type = 'application/javascript';
|
if (ext === '.js') type = 'application/javascript';
|
||||||
callback({ data: content, mimeType: type } as any);
|
callback({ data: content, mimeType: type } as any);
|
||||||
}, (error) => {
|
|
||||||
if (error) done(error);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const w = new BrowserWindow({
|
const w = new BrowserWindow({
|
||||||
|
@ -431,7 +429,8 @@ describe('chromium features', () => {
|
||||||
customSession.clearStorageData({
|
customSession.clearStorageData({
|
||||||
storages: ['serviceworkers']
|
storages: ['serviceworkers']
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
customSession.protocol.uninterceptProtocol('file', error => done(error));
|
customSession.protocol.uninterceptProtocol('file');
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -840,8 +839,8 @@ describe('chromium features', () => {
|
||||||
];
|
];
|
||||||
const s = (url: string) => url.startsWith('file') ? 'file://...' : url;
|
const s = (url: string) => url.startsWith('file') ? 'file://...' : url;
|
||||||
|
|
||||||
before(async () => {
|
before(() => {
|
||||||
await promisify(protocol.registerFileProtocol)(scheme, (request, callback) => {
|
protocol.registerFileProtocol(scheme, (request, callback) => {
|
||||||
if (request.url.includes('blank')) {
|
if (request.url.includes('blank')) {
|
||||||
callback(`${fixturesPath}/pages/blank.html`);
|
callback(`${fixturesPath}/pages/blank.html`);
|
||||||
} else {
|
} else {
|
||||||
|
@ -849,8 +848,8 @@ describe('chromium features', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
after(async () => {
|
after(() => {
|
||||||
await promisify(protocol.unregisterProtocol)(scheme);
|
protocol.unregisterProtocol(scheme);
|
||||||
});
|
});
|
||||||
afterEach(closeAllWindows);
|
afterEach(closeAllWindows);
|
||||||
|
|
||||||
|
@ -929,7 +928,7 @@ describe('chromium features', () => {
|
||||||
describe('custom non standard schemes', () => {
|
describe('custom non standard schemes', () => {
|
||||||
const protocolName = 'storage';
|
const protocolName = 'storage';
|
||||||
let contents: WebContents;
|
let contents: WebContents;
|
||||||
before((done) => {
|
before(() => {
|
||||||
protocol.registerFileProtocol(protocolName, (request, callback) => {
|
protocol.registerFileProtocol(protocolName, (request, callback) => {
|
||||||
const parsedUrl = url.parse(request.url);
|
const parsedUrl = url.parse(request.url);
|
||||||
let filename;
|
let filename;
|
||||||
|
@ -942,11 +941,11 @@ describe('chromium features', () => {
|
||||||
default : filename = '';
|
default : filename = '';
|
||||||
}
|
}
|
||||||
callback({ path: `${fixturesPath}/pages/storage/${filename}` });
|
callback({ path: `${fixturesPath}/pages/storage/${filename}` });
|
||||||
}, (error) => done(error));
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after((done) => {
|
after(() => {
|
||||||
protocol.unregisterProtocol(protocolName, () => done());
|
protocol.unregisterProtocol(protocolName);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
|
@ -217,16 +217,16 @@ describe('<webview> tag', function () {
|
||||||
const zoomScheme = standardScheme;
|
const zoomScheme = standardScheme;
|
||||||
const webviewSession = session.fromPartition('webview-temp');
|
const webviewSession = session.fromPartition('webview-temp');
|
||||||
|
|
||||||
before((done) => {
|
before(() => {
|
||||||
const protocol = webviewSession.protocol;
|
const protocol = webviewSession.protocol;
|
||||||
protocol.registerStringProtocol(zoomScheme, (request, callback) => {
|
protocol.registerStringProtocol(zoomScheme, (request, callback) => {
|
||||||
callback('hello');
|
callback('hello');
|
||||||
}, (error) => done(error));
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
after((done) => {
|
after(() => {
|
||||||
const protocol = webviewSession.protocol;
|
const protocol = webviewSession.protocol;
|
||||||
protocol.unregisterProtocol(zoomScheme, (error) => done(error));
|
protocol.unregisterProtocol(zoomScheme);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('inherits the zoomFactor of the parent window', async () => {
|
it('inherits the zoomFactor of the parent window', async () => {
|
||||||
|
|
|
@ -897,13 +897,9 @@ app.whenReady().then(() => {
|
||||||
callback({ url: request.url, method: request.method })
|
callback({ url: request.url, method: request.method })
|
||||||
})
|
})
|
||||||
|
|
||||||
protocol.unregisterProtocol('atom', (error) => {
|
protocol.unregisterProtocol('atom')
|
||||||
console.log(error ? error.message : 'ok')
|
|
||||||
})
|
|
||||||
|
|
||||||
protocol.isProtocolHandled('atom').then(handled => {
|
const registered: boolean = protocol.isProtocolRegistered('atom')
|
||||||
console.log(handled)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// tray
|
// tray
|
||||||
|
@ -1195,10 +1191,6 @@ app.whenReady().then(function () {
|
||||||
protocol.registerFileProtocol('atom', function (request, callback) {
|
protocol.registerFileProtocol('atom', function (request, callback) {
|
||||||
const url = request.url.substr(7)
|
const url = request.url.substr(7)
|
||||||
callback(path.normalize(__dirname + '/' + url))
|
callback(path.normalize(__dirname + '/' + url))
|
||||||
}, function (error) {
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to register protocol')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue