Skip to content

Commit

Permalink
adds IPFS to page only when option is set
Browse files Browse the repository at this point in the history
  • Loading branch information
alanshaw committed Jan 22, 2018
1 parent 05b3b4c commit 0e42bdf
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 70 deletions.
14 changes: 0 additions & 14 deletions add-on/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,6 @@
"page": "dist/background/background.html"
},

"content_scripts": [
{
"matches": [
"<all_urls>"
],
"match_about_blank": true,
"js": [
"dist/contentScripts/ipfs-proxy/content.js"
],
"run_at": "document_start",
"all_frames": true
}
],

"browser_action": {
"browser_style": false,
"default_icon": {
Expand Down
39 changes: 17 additions & 22 deletions add-on/src/contentScripts/ipfs-proxy/content.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
'use strict'
/* eslint-env browser, webextensions */

const browser = require('webextension-polyfill')
const once = require('./once')
const injectScript = require('./inject-script')

const port = browser.runtime.connect({ name: 'ipfs-proxy' })
window.ipfsCompanion = window.ipfsCompanion || {}
window.ipfsCompanion.once = window.ipfsCompanion.once || {}

// Forward on messages from background to the page and vice versa
port.onMessage.addListener((data) => window.postMessage(data, '*'))
// Only run this once for this window!
// URL can change (history API) which causes this script to be executed again,
// but it only needs to be setup once per window...
once('ipfsProxyContentScriptExecuted', () => {
const port = browser.runtime.connect({ name: 'ipfs-proxy' })

window.addEventListener('message', (msg) => {
if (msg.data && msg.data.sender === 'postmsg-rpc/client') {
port.postMessage(msg.data)
}
})
// Forward on messages from background to the page and vice versa
port.onMessage.addListener((data) => window.postMessage(data, '*'))

function injectPageScript () {
try {
const scriptTag = document.createElement('script')
scriptTag.src = browser.extension.getURL('dist/contentScripts/ipfs-proxy/page.js')
scriptTag.onload = function () {
this.parentNode.removeChild(this)
window.addEventListener('message', (msg) => {
if (msg.data && msg.data.sender === 'postmsg-rpc/client') {
port.postMessage(msg.data)
}
const container = document.head || document.documentElement
container.insertBefore(scriptTag, container.children[0])
} catch (err) {
console.error('Failed to inject ipfs-proxy/page.js', err)
}
}
})

injectPageScript()
injectScript(browser.extension.getURL('dist/contentScripts/ipfs-proxy/page.js'))
}, { store: window.ipfsCompanion.once })()
15 changes: 15 additions & 0 deletions add-on/src/contentScripts/ipfs-proxy/inject-script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function injectScript (src, target, opts) {
opts = opts || {}
const doc = opts.document || document

const scriptTag = doc.createElement('script')
scriptTag.src = src
scriptTag.onload = function () {
this.parentNode.removeChild(this)
}

target = doc.head || doc.documentElement
target.appendChild(scriptTag)
}

module.exports = injectScript
18 changes: 18 additions & 0 deletions add-on/src/contentScripts/ipfs-proxy/once.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const store = {}

// call a function only once and store it's return value
function once (id, func, opts) {
opts = opts || {}
opts.store = opts.store || store

if (Object.keys(opts.store).includes(id)) {
return () => opts.store[id]
}

return function () {
opts.store[id] = func.apply(null, arguments)
return opts.store[id]
}
}

module.exports = once
4 changes: 3 additions & 1 deletion add-on/src/lib/ipfs-companion.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ module.exports = async function init () {
onCopyAddressAtPublicGw: () => copier.copyAddressAtPublicGw()
})
modifyRequest = createRequestModifier(getState, dnsLink, ipfsPathValidator)
ipfsProxy = createIpfsProxy(() => ipfs)
ipfsProxy = createIpfsProxy(() => ipfs, getState)
registerListeners()
await setApiStatusUpdateInterval(options.ipfsApiPollMs)
await storeMissingOptions(
Expand Down Expand Up @@ -525,6 +525,8 @@ module.exports = async function init () {
state.dnslink = change.newValue
} else if (key === 'preloadAtPublicGateway') {
state.preloadAtPublicGateway = change.newValue
} else if (key === 'ipfsProxy') {
state.ipfsProxy = change.newValue
}
}
}
Expand Down
98 changes: 69 additions & 29 deletions add-on/src/lib/ipfs-proxy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,47 @@ const browser = require('webextension-polyfill')
const { createProxyServer, closeProxyServer } = require('ipfs-postmsg-proxy')
const AccessControl = require('./access-control')

module.exports = function createIpfsProxy (getIpfs) {
const ACL_FUNCTIONS = [
'block.put',
'config.set',
'config.get',
'config.replace',
'dag.put',
'dht.put',
'dht.provide',
'files.add',
'key.get',
'key.list',
'key.rename',
'key.rm',
'object.new',
'object.put',
'object.patch.addLink',
'object.patch.rmLink',
'object.patch.appendData',
'object.patch.setData',
'pin.add',
'pin.rm',
'pubsub.publish',
'swarm.connect',
'swarm.disconnect'
]

function createIpfsProxy (getIpfs, getState) {
let connections = []
const accessControl = new AccessControl()

const onConnect = (port) => {
const onPortConnect = (port) => {
if (port.name !== 'ipfs-proxy') return

const { origin } = new URL(port.sender.url)

const proxy = createProxyServer(getIpfs, {
addListener: (_, handler) => port.onMessage.addListener(handler),
removeListener: (_, handler) => port.onMessage.removeListener(handler),
postMessage: (data) => port.postMessage(data),
getMessageData: (d) => d,
pre: [
'block.put',
'config.set',
'config.get',
'config.replace',
'dag.put',
'dht.put',
'dht.provide',
'files.add',
'key.get',
'key.list',
'key.rename',
'key.rm',
'object.new',
'object.put',
'object.patch.addLink',
'object.patch.rmLink',
'object.patch.appendData',
'object.patch.setData',
'pin.add',
'pin.rm',
'pubsub.publish',
'swarm.connect',
'swarm.disconnect'
].reduce((obj, permission) => {
pre: ACL_FUNCTIONS.reduce((obj, permission) => {
obj[permission] = createAclPreCall(accessControl, origin, permission)
return obj
}, {})
Expand All @@ -60,11 +64,47 @@ module.exports = function createIpfsProxy (getIpfs) {
connections.push({ close })
}

browser.runtime.onConnect.addListener(onConnect)
browser.runtime.onConnect.addListener(onPortConnect)

const onTabUpdated = (tabId, changeInfo, tab) => {
// Some devtools tabs do not have an ID
if (!tabId || tabId === browser.tabs.TAB_ID_NONE) return

// If IPFS proxy option is not enabled do not execute the content script
if (!getState().ipfsProxy) return

// Only inject on http(s): ipfs: or dweb:
if (!['http', 'ipfs', 'dweb'].some(p => (tab.url || '').startsWith(p))) return

// Only inject when loaded
if (changeInfo.status !== 'complete') return

try {
browser.tabs.executeScript(tab.id, {
file: browser.extension.getURL('dist/contentScripts/ipfs-proxy/content.js'),
runAt: 'document_start',
allFrames: true
})
} catch (err) {
console.error('Failed to execute IPFS proxy content script', err)
}
}

browser.tabs.onUpdated.addListener(onTabUpdated)

return { destroy: () => connections.forEach(c => c.destroy) }
const handle = {
destroy () {
connections.forEach(c => c.destroy)
browser.runtime.onConnect.removeListener(onPortConnect)
browser.tabs.onUpdated.removeListener(onTabUpdated)
}
}

return handle
}

module.exports = createIpfsProxy

function createAclPreCall (accessControl, origin, permission) {
return async (...args) => {
let access = await accessControl.getAccess(origin, permission)
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
"build:copy:wx-polyfill-lib": "shx cp node_modules/webextension-polyfill/dist/browser-polyfill.min.js add-on/dist/contentScripts/browser-polyfill.min.js",
"build:js": "browserify -p prundupify -t browserify-css -t [ browserify-package-json --global ] add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action/index.js add-on/src/popup/quick-upload.js add-on/src/pages/proxy-acl.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action/browser-action.js -o add-on/dist/popup/quick-upload.js -o add-on/dist/pages/proxy-acl.js ] -o add-on/dist/ipfs-companion-common.js",
"build:content-scripts": "run-p build:content-scripts:**",
"build:content-scripts:ipfs-proxy:content": "browserify add-on/src/contentScripts/ipfs-proxy/content.js -o add-on/dist/contentScripts/ipfs-proxy/content.js",
"build:content-scripts:ipfs-proxy:page": "browserify add-on/src/contentScripts/ipfs-proxy/page.js -o add-on/dist/contentScripts/ipfs-proxy/page.js",
"build:content-scripts:ipfs-proxy:content": "browserify -s IpfsProxyContent add-on/src/contentScripts/ipfs-proxy/content.js -o add-on/dist/contentScripts/ipfs-proxy/content.js",
"build:content-scripts:ipfs-proxy:page": "browserify -s IpfsProxyPage add-on/src/contentScripts/ipfs-proxy/page.js -o add-on/dist/contentScripts/ipfs-proxy/page.js",
"build:minimize-dist": "shx rm -rf add-on/dist/lib",
"build:bundle-extension": "web-ext build -s add-on/ -i src/ -a build/",
"watch": "run-p watch:*",
"watch:js": "watchify -p prundupify -t browserify-css -t [ browserify-package-json --global ] add-on/src/background/background.js add-on/src/options/options.js add-on/src/popup/browser-action/index.js add-on/src/popup/quick-upload.js add-on/src/pages/proxy-acl.js -p [ factor-bundle -o add-on/dist/background/background.js -o add-on/dist/options/options.js -o add-on/dist/popup/browser-action/browser-action.js -o add-on/dist/popup/quick-upload.js -o add-on/dist/pages/proxy-acl.js ] -o add-on/dist/ipfs-companion-common.js -v",
"watch:content-scripts": "run-p watch:content-scripts:**",
"watch:content-scripts:ipfs-proxy:content": "watchify add-on/src/contentScripts/ipfs-proxy/content.js -o add-on/dist/contentScripts/ipfs-proxy/content.js",
"watch:content-scripts:ipfs-proxy:page": "watchify add-on/src/contentScripts/ipfs-proxy/page.js -o add-on/dist/contentScripts/ipfs-proxy/page.js",
"watch:content-scripts:ipfs-proxy:content": "watchify -s IpfsProxyContent add-on/src/contentScripts/ipfs-proxy/content.js -o add-on/dist/contentScripts/ipfs-proxy/content.js",
"watch:content-scripts:ipfs-proxy:page": "watchify -s IpfsProxyPage add-on/src/contentScripts/ipfs-proxy/page.js -o add-on/dist/contentScripts/ipfs-proxy/page.js",
"test": "run-s test:*",
"test:functional": "mocha test/functional/**/*.test.js",
"lint": "run-s lint:*",
Expand Down

0 comments on commit 0e42bdf

Please sign in to comment.