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

feat: support page actions for CID subdomains #537

Merged
merged 1 commit into from
Jul 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion add-on/src/lib/ipfs-companion.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ module.exports = async function init () {
async function updatePageActionIndicator (tabId, url) {
// Chrome does not permit for both pageAction and browserAction to be enabled at the same time
// https://github.com/ipfs-shipyard/ipfs-companion/issues/398
if (runtime.isFirefox && ipfsPathValidator.validIpfsOrIpnsUrl(url)) {
if (runtime.isFirefox && ipfsPathValidator.isIpfsPageActionsContext(url)) {
if (url.startsWith(state.gwURLString) || url.startsWith(state.apiURLString)) {
await browser.pageAction.setIcon({ tabId: tabId, path: '/icons/ipfs-logo-on.svg' })
await browser.pageAction.setTitle({ tabId: tabId, title: browser.i18n.getMessage('pageAction_titleIpfsAtCustomGateway') })
Expand Down
14 changes: 12 additions & 2 deletions add-on/src/lib/ipfs-path.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
const IsIpfs = require('is-ipfs')

function safeIpfsPath (urlOrPath) {
if (IsIpfs.subdomain(urlOrPath)) {
urlOrPath = subdomainToIpfsPath(urlOrPath)
}
// better safe than sorry: https://github.com/ipfs/ipfs-companion/issues/303
return decodeURIComponent(urlOrPath.replace(/^.*(\/ip(f|n)s\/.+)$/, '$1'))
}

function subdomainToIpfsPath (urlString) {
const url = new URL(urlString)
const fqdn = url.hostname.split('.')
const cid = fqdn[0]
const protocol = fqdn[1]
Comment on lines +16 to +18
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realized this won't produce correct results for gateways under multi-leveled domains such as cid.ipfs.something.co.uk.
Easy fix is to switch to is-ipfs, probably something like:

const { subdomainPattern } = require('is-ipfs')

const match = fqdn.match(subdomainPattern)
if (!match) throw new Error('no match for isIPFS.subdomainPattern')
const protocol = match[1]
const cid = match[2]

return `/${protocol}/${cid}${url.pathname}`
}

exports.safeIpfsPath = safeIpfsPath

function urlAtPublicGw (path, pubGwUrl) {
Expand Down Expand Up @@ -41,9 +52,8 @@ function createIpfsPathValidator (getState, dnsLink) {
},

// Test if actions such as 'copy URL', 'pin/unpin' should be enabled for the URL
// (we explicitly disable IPNS for now as there is no support for pins)
isIpfsPageActionsContext (url) {
return IsIpfs.url(url) && !url.startsWith(getState().apiURLString)
return (IsIpfs.url(url) && !url.startsWith(getState().apiURLString)) || IsIpfs.subdomain(url)
}
}

Expand Down
10 changes: 5 additions & 5 deletions add-on/src/popup/browser-action/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ module.exports = (state, emitter) => {

try {
const ipfs = await getIpfsApi()
const currentPath = await resolveToIPFS(ipfs, new URL(state.currentTab.url).pathname)
const currentPath = await resolveToIPFS(ipfs, state.currentTab.url)
const pinResult = await ipfs.pin.add(currentPath, { recursive: true })
console.log('ipfs.pin.add result', pinResult)
state.isPinned = true
Expand All @@ -90,7 +90,7 @@ module.exports = (state, emitter) => {

try {
const ipfs = await getIpfsApi()
const currentPath = await resolveToIPFS(ipfs, new URL(state.currentTab.url).pathname)
const currentPath = await resolveToIPFS(ipfs, state.currentTab.url)
const result = await ipfs.pin.rm(currentPath, {recursive: true})
state.isPinned = false
console.log('ipfs.pin.rm result', result)
Expand Down Expand Up @@ -244,7 +244,7 @@ module.exports = (state, emitter) => {
// skip update if there is an ongoing pin or unpin
if (state.isPinning || state.isUnPinning) return
try {
const currentPath = await resolveToIPFS(ipfs, new URL(status.currentTab.url).pathname)
const currentPath = await resolveToIPFS(ipfs, status.currentTab.url)
const response = await ipfs.pin.ls(currentPath, {quiet: true})
console.log(`positive ipfs.pin.ls for ${currentPath}: ${JSON.stringify(response)}`)
state.isPinned = true
Expand Down Expand Up @@ -273,8 +273,8 @@ async function getIpfsApi () {
return (bg && bg.ipfsCompanion) ? bg.ipfsCompanion.ipfs : null
}

async function resolveToIPFS (ipfs, path) {
path = safeIpfsPath(path) // https://github.com/ipfs/ipfs-companion/issues/303
async function resolveToIPFS (ipfs, urlOrPath) {
let path = safeIpfsPath(urlOrPath) // https://github.com/ipfs/ipfs-companion/issues/303
if (/^\/ipns/.test(path)) {
const response = await ipfs.name.resolve(path, {recursive: true, nocache: false})
return response.Path
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"ipfs-css": "0.5.2",
"ipfs-http-response": "0.1.2",
"ipfs-postmsg-proxy": "3.0.0",
"is-ipfs": "0.3.2",
"is-ipfs": "0.4.2",
"is-svg": "3.0.0",
"lru_map": "0.3.3",
"mime-types": "2.1.18",
Expand Down
20 changes: 20 additions & 0 deletions test/functional/lib/ipfs-path.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,24 @@ describe('ipfs-path.js', function () {
})
})
})
describe('isIpfsPageActionsContext', function () {
it('should return true for URL at IPFS Gateway', function () {
const url = 'https://ipfs.io/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR?argTest#hashTest'
expect(ipfsPathValidator.isIpfsPageActionsContext(url)).to.equal(true)
})
it('should return true for URL at IPFS Gateway with Base32 CIDv1 in subdomain', function () {
// context-actions are shown on publick gateways that use CID in subdomain as well
const url = 'http://bafkreigh2akiscaildcqabsyg3dfr6chu3fgpregiymsck7e7aqa4s52zy.ipfs.dweb.link/'
expect(ipfsPathValidator.isIpfsPageActionsContext(url)).to.equal(true)
})
it('should return false for URL at IPFS Gateway with Base58 CIDv0 in subdomain', function () {
// context-actions are shown on publick gateways that use CID in subdomain as well
const url = 'http://QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR.ipfs.dweb.link/'
expect(ipfsPathValidator.isIpfsPageActionsContext(url)).to.equal(false)
})
it('should return false for non-IPFS URL', function () {
const url = 'https://ipfs.io/ipfs/NotACid?argTest#hashTest'
expect(ipfsPathValidator.isIpfsPageActionsContext(url)).to.equal(false)
})
})
})
15 changes: 15 additions & 0 deletions test/functional/lib/ipfs-request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,21 @@ describe('modifyRequest.onBeforeRequest', function () {
})
})

describe('request to FQDN with valid CID in subdomain', function () {
// we do not touch such requests for now, as HTTP-based local node usually can't provide the same origin-based guarantees
// we will redirect subdomains to ipfs:// when native handler is available
it('should be left untouched for IPFS', function () {
state.redirect = true
const request = url2request('http://bafybeigxjv2o4jse2lajbd5c7xxl5rluhyqg5yupln42252e5tcao7hbge.ipfs.dweb.link/')
expect(modifyRequest.onBeforeRequest(request)).to.equal(undefined)
})
it('should be left untouched for IPNS', function () {
state.redirect = true
const request = url2request('http://bafybeigxjv2o4jse2lajbd5c7xxl5rluhyqg5yupln42252e5tcao7hbge.ipns.dweb.link/')
expect(modifyRequest.onBeforeRequest(request)).to.equal(undefined)
})
})

describe('request to FQDN with dnslink experiment enabled', function () {
let activeGateway
beforeEach(function () {
Expand Down
27 changes: 18 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1602,16 +1602,16 @@ browserslist@^3.2.6:
caniuse-lite "^1.0.30000844"
electron-to-chromium "^1.3.47"

bs58@=2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.0.tgz#72b713bed223a0ac518bbda0e3ce3f4817f39eb5"

bs58@^4.0.0, bs58@^4.0.1:
bs58@4.0.1, bs58@^4.0.0, bs58@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a"
dependencies:
base-x "^3.0.2"

bs58@=2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.0.tgz#72b713bed223a0ac518bbda0e3ce3f4817f39eb5"

bs58check@<3.0.0, bs58check@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.1.tgz#8a5d0e587af97b784bf9cbf1b29f454d82bc0222"
Expand Down Expand Up @@ -1994,7 +1994,7 @@ ci-info@^1.0.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2"

cids@^0.5.2, cids@^0.5.3, cids@~0.5.1, cids@~0.5.2, cids@~0.5.3:
cids@0.5.3, cids@^0.5.2, cids@^0.5.3, cids@~0.5.1, cids@~0.5.2, cids@~0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/cids/-/cids-0.5.3.tgz#9a25b697eb76faf807afcec35c4ab936edfbd0a4"
dependencies:
Expand Down Expand Up @@ -5329,7 +5329,16 @@ is-installed-globally@^0.1.0:
global-dirs "^0.1.0"
is-path-inside "^1.0.0"

is-ipfs@0.3.2, is-ipfs@~0.3.2:
is-ipfs@0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/is-ipfs/-/is-ipfs-0.4.2.tgz#06a858769cbfdac39a3e0ed1ca157e3f3fcc84fc"
dependencies:
bs58 "4.0.1"
cids "0.5.3"
multibase "0.4.0"
multihashes "0.4.13"

is-ipfs@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-ipfs/-/is-ipfs-0.3.2.tgz#c4650b838e36fd0151de5896b2ff319fe8936182"
dependencies:
Expand Down Expand Up @@ -7016,7 +7025,7 @@ multiaddr@^5.0.0:
varint "^5.0.0"
xtend "^4.0.1"

multibase@~0.4.0:
multibase@0.4.0, multibase@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.4.0.tgz#1bdb62c82de0114f822a1d8751bcbee91cd2efba"
dependencies:
Expand All @@ -7041,7 +7050,7 @@ multicodec@~0.2.7:
dependencies:
varint "^5.0.0"

multihashes@^0.4.13, multihashes@~0.4.12, multihashes@~0.4.13, multihashes@~0.4.9:
multihashes@0.4.13, multihashes@^0.4.13, multihashes@~0.4.12, multihashes@~0.4.13, multihashes@~0.4.9:
version "0.4.13"
resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.13.tgz#d10bd71bd51d24aa894e2a6f1457146bb7bac125"
dependencies:
Expand Down