Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Merge pull request #11950 from brave/issue-11945
Browse files Browse the repository at this point in the history
Hardening for ledger errors
  • Loading branch information
bsclifton committed Nov 15, 2017
1 parent c1bd722 commit 82ef6f1
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
18 changes: 16 additions & 2 deletions app/browser/api/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,11 @@ const roundtrip = (params, options, callback) => {
if (err) return callback(err, response)

if (Math.floor(response.statusCode / 100) !== 2) {
if (params.useProxy && response.statusCode === 403) {
params.useProxy = false
return roundtrip(params, options, callback)
}

return callback(
new Error('HTTP response ' + response.statusCode + ' for ' + params.method + ' ' + params.path),
response)
Expand Down Expand Up @@ -2089,6 +2094,8 @@ const getNewClient = () => {
return newClient
}

let busyRetryCount = 0

const transitionWalletToBat = () => {
let newPaymentId, result

Expand Down Expand Up @@ -2159,7 +2166,13 @@ const transitionWalletToBat = () => {
}

if (client.busyP()) {
console.log('ledger client is currently busy; transition will be retried on next launch')
if (++busyRetryCount > 3) {
console.log('ledger client is currently busy; transition will be retried on next launch')
return
}
const delayTime = random.randomInt({ min: miliseconds.minute, max: 10 * miliseconds.minute })
console.log('ledger client is currently busy; transition will be retried shortly (this was attempt ' + busyRetryCount + ')')
setTimeout(() => transitionWalletToBat(), delayTime)
return
}

Expand Down Expand Up @@ -2378,7 +2391,8 @@ const getMethods = () => {
},
getCurrentMediaKey: (key) => currentMediaKey,
synopsisNormalizer,
checkVerifiedStatus
checkVerifiedStatus,
roundtrip
}
}

Expand Down
97 changes: 97 additions & 0 deletions test/unit/app/browser/api/ledgerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('ledger api unit tests', function () {
let tabState = Immutable.fromJS({
partition: 'persist:partition-1'
})
let request

// constants
const xhr = 'https://www.youtube.com/api/stats/watchtime?docid=kLiLOkzLetE&st=11.338&et=21.339'
Expand Down Expand Up @@ -72,6 +73,8 @@ describe('ledger api unit tests', function () {
return false
}
})
request = require('../../../../../js/lib/request')
mockery.registerMock('../../../js/lib/request', request)
mockery.registerMock('../../../js/actions/appActions', appActions)
onBitcoinToBatTransitionedSpy = sinon.spy(appActions, 'onBitcoinToBatTransitioned')
onLedgerCallbackSpy = sinon.spy(appActions, 'onLedgerCallback')
Expand Down Expand Up @@ -432,8 +435,14 @@ describe('ledger api unit tests', function () {
})

describe('transitionWalletToBat', function () {
let fakeClock

before(function () {
fakeClock = sinon.useFakeTimers()
})
after(function () {
ledgerApi.setSynopsis(undefined)
fakeClock.restore()
})

describe('when client is not busy', function () {
Expand Down Expand Up @@ -881,4 +890,92 @@ describe('ledger api unit tests', function () {
assert.deepEqual(state.toJS(), expectedState.toJS())
})
})

describe('roundtrip', function () {
let requestStub
const simpleCallback = sinon.stub()
let responseCode = 200

before(function () {
requestStub = sinon.stub(request, 'request', (options, callback) => {
switch (responseCode) {
case 403:
callback(null, {
statusCode: 403,
headers: {},
statusMessage: '<html><body>Your requested URL has been blocked by the URL Filter database module of {{EnterpriseName}}. The URL is listed in categories that are not allowed by your administrator at this time.</body></html>',
httpVersionMajor: 1,
httpVersionMinor: 1
})
break
case 200:
default:
callback(null, {
statusCode: 200,
headers: {},
statusMessage: '',
httpVersionMajor: 1,
httpVersionMinor: 1
}, {timestamp: '6487805648321904641'})
}
})
})

after(function () {
requestStub.restore()
})

describe('when params.useProxy is true', function () {
let expectedOptions
before(function () {
expectedOptions = {
url: 'https://ledger-proxy.privateinternetaccess.com/v3/publisher/timestamp',
method: 'GET',
payload: undefined,
responseType: 'text',
headers: { 'content-type': 'application/json; charset=utf-8' },
verboseP: undefined
}
requestStub.reset()
simpleCallback.reset()
ledgerApi.roundtrip({
server: 'https://ledger.brave.com',
path: '/v3/publisher/timestamp',
useProxy: true
}, {}, simpleCallback)
})

it('updates URL to use proxy (ledger-proxy.privateinternetaccess.com)', function () {
assert(requestStub.withArgs(expectedOptions, sinon.match.func).called)
})

it('calls the callback on success', function () {
assert(simpleCallback.calledOnce)
})

describe('when the proxy returns a 403', function () {
before(function () {
responseCode = 403
requestStub.reset()
ledgerApi.roundtrip({
server: 'https://ledger.brave.com',
path: '/v3/publisher/timestamp',
useProxy: true
}, {}, simpleCallback)
})
after(function () {
responseCode = 200
})
it('calls request a second time (with useProxy = false)', function () {
assert(requestStub.calledTwice)
assert(requestStub.withArgs(expectedOptions, sinon.match.func).called)

const secondCallOptions = Object.assign({}, expectedOptions, {
url: 'https://ledger.brave.com/v3/publisher/timestamp'
})
assert(requestStub.withArgs(secondCallOptions, sinon.match.func).called)
})
})
})
})
})
6 changes: 5 additions & 1 deletion test/unit/lib/fakeElectron.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ const fakeElectron = {
},
session: {
defaultSession: {
partition: 'default'
partition: 'default',
webRequest: {
fetch: function (url, options, handler) {
}
}
}
},
extensions: {
Expand Down

0 comments on commit 82ef6f1

Please sign in to comment.