Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature-detection of chrome.sockets #711

Merged
merged 21 commits into from
Apr 16, 2019
Merged

Conversation

lidel
Copy link
Member

@lidel lidel commented Apr 16, 2019

Part of an effort to run embedded js-ipfs in Brave 🦁 #664

TL;DR

This PR adds runtime dectection of chrome.sockets APIs and a build target for testing it with Brave Nightly: yarn dev-build bundle:brave

What is new?

This PR adds new tests and should not modify existing functionality unless user is running Brave Nightly.

External node type remains the default, but Brave users can opt-in to "Embedded + chrome.sockets" node type on the Preferences screen, which will enable Embedded HTTP Gateway.

2019-04-16-220411_1133x593_scrot

Details

This PR includes cherry-picked js-ipfs improvements:

Other

  • Brave users will see a new node type: embedded:chromesockets (5c0b495)
  • cleanup boot on clean install (2b63636)
  • new runtime-checks: isBrave, hasChromeSocketsForTcp
  • peer discovery over a ws-star to improve things until we have TCP transport, MulticastDNS and DHT

Second checkpoint: I took js-ipfs `0.35.0-pre.0` for a spin.
It ships with [hapi.js](https://github.com/hapijs) v18, HTTP server used
for exposing Gateway.

Done:

- [x] start raw `http` server (`http.createServer`)
- [x] start raw `hapi` server (`Hapi.Server`) (screenshot below)
    - after some troubleshooting I managed to start raw Hapi server
      but got internal error for all responses
- [x] return valid response from  `hapi` server running in browser extension
    - got it to work by replacing `url` with
      [iso-url](https://www.npmjs.com/package/iso-url) during webpack build

Next:

- [ ] start embedded js-ipfs with Gateway exposed by embedded Hapi server
    - right now `new Ipfs(..)` fails due to `TypeError: this._dht.on is
      not a function`,
      it seems libp2p does not disable DHT fully when we polyfill
      `net`/`dgram` using `chrome.sockets`
- [ ] start js-ipfs-http-client
    - does not work due to `TypeError: res.req.getHeaders is not
    a function` – probably `http` API mismatch between expected and one
    provided by chrome.sockets polyfil
Disabling DHT in options.libp2p.config solved
TypeError: this._dht.on is not a function
(disabling it in options.config was not enough)
This adds npm run bundle:brave:beta which outputs package into
build/brave/beta with the ID of the chrome beta channel
This switches to patched js-ipfs which enables us to initi and start HttpApi
in standalone, embedded mode with chrome.sockets
(without running jsipfs daemon in CLI)

Yes. I know. We are running two HTTP servers in HTTP browser :-))

Quick status:
Requests to API port (5002) such as /api/v0/id work.
Requests to Gateway (9090) are a mixed bag. Directory listings work, but
returning byte streams does not work yet.
WIP hapi patch: detect browserified streams in Chrome App environment

Detection via `stream instanceof Stream` does not work correctly in
browser context, especially when different polyfils are used and mixed
together.

This replaces instanceof check with feature-detection, which enables
Hapi to consume stream-like objects, as long they match proper contract.

WIP js-ipfs patch: do proper streaming and content-type sniffing

1. Simplifies code responsible for streaming response and makes the
streaming actually work by telling the payload compression stream to
flush its content on every read().  (previous version was buffering
entire thing in Hapi's compressor memory)

2. Content-type sniffing is now done over first 512 bytes.
chrome-net patch:
https://github.com/lidel/chrome-net/commit/838ffde4a33721888f74783821e0486dfcc88797

  chrome-net did not check if chrome.sockets.* actually exist.
  This caused problems with extensions built for Chromium-based browsers
  that tried to maintain the single codebase and do feature-detection
  at runtime.

feature detection for embedded js-ipfs:

  If chrome.sockets is available, embedded-brave.js will be used
  instead of regular embedded.js

notify user about socket errors:

  If port is already taken, a notification is displayed.
  We will most likely improve this soon (eg. by finding the next free port)
  but is good enough for now.
This adds new ipfsNodeType for use in Chromium contexts such as Brave.

For now we do naive check if chrome.sockets.tcp* APIs are available
and switch to ipfsNodeType=embedded:chromesockets if true.

User can customize configuration of embedded js-ipfs node via Preferences.
The very first time extension started was broken, node got restarted
multiple times due to config updates happening in lib/options.js

This change simplifies boot process to the point no restarts are
triggered by config updates on the first run. Landing page is also fixed
to properly receive notification about new peers being available.

We switched to ipfs.io for DNS resolution until DNSLink support lands in
js-ipfs and we get better understanding how to operate
chrome.sockets.udp API

Tests for relevant code paths are updated and embedded js-ipfs with
chrome.sockets now listens on custom ports, removing the need of
changing configuration if someone is already running go-ipfs or js-ipfs
This applies cherry-picked patches from:
ipfs/js-ipfs#1989
ipfs/js-ipfs#1950
and solves stream issues on page refresh.

Content-type sniffing is now done over a meaningful amount of bytes
instead of arbitrary number.
This should improve things until we have TCP transport, MulticastDNS and DHT
Embedded node with chrome.sockets is not ready yet.
Key blockers in js-ipfs need to be resolved first:
- /ipns/<fqdn>/ load fine
- sharded directories (e.g. wikipedia) load fine

We may also decide to keep External as default and just add a button
on Welcome screen that activates embedded note.
@ghost ghost assigned lidel Apr 16, 2019
@ghost ghost added the status/in-progress In progress label Apr 16, 2019
@lidel lidel merged commit 01bcdf2 into master Apr 16, 2019
@ghost ghost removed the status/in-progress In progress label Apr 16, 2019
@lidel
Copy link
Member Author

lidel commented Apr 16, 2019

(Merging this in fast-track mode as we want to ship this to Beta channel this week to unblock development on Brave side. Feel free to review/comment anyway.)

@lidel lidel deleted the feat/brave-build-with-chrome-sockets branch April 17, 2019 12:33
@lidel lidel added the area/brave Issues related to Brave Browser label Apr 23, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/brave Issues related to Brave Browser
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant